rasn1 0.6.6 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RASN1
2
4
  module Types
3
-
4
5
  # ASN.1 Null
5
6
  # @author Sylvain Daubert
6
7
  class Null < Primitive
7
- TAG = 0x05
8
+ # Null id value
9
+ ID = 0x05
8
10
 
9
11
  # @return [String]
10
12
  def inspect(level=0)
11
- str = ''
12
- str << ' ' * level if level > 0
13
- str << "#{@name} " unless @name.nil?
14
- str << "#{type}"
15
- str << " OPTIONAL" if optional?
13
+ str = common_inspect(level)[0..-2] # remove terminal ':'
14
+ str << ' OPTIONAL' if optional?
16
15
  str
17
16
  end
18
17
 
@@ -23,7 +22,8 @@ module RASN1
23
22
  end
24
23
 
25
24
  def der_to_value(der, ber: false)
26
- raise ASN1Error, "NULL TAG should not have content!" if der.length > 0
25
+ raise ASN1Error, 'NULL should not have content!' if der.length.positive?
26
+
27
27
  @value = nil
28
28
  end
29
29
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RASN1
2
4
  module Types
3
-
4
5
  # ASN.1 Numeric String
5
6
  # @author Sylvain Daubert
6
7
  class NumericString < OctetString
7
- TAG = 18
8
+ # NumericString id value
9
+ ID = 18
8
10
 
9
11
  # Get ASN.1 type
10
12
  # @return [String]
@@ -13,21 +15,19 @@ module RASN1
13
15
  end
14
16
 
15
17
  private
16
-
18
+
17
19
  def value_to_der
18
20
  check_characters
19
21
  @value.to_s.force_encoding('BINARY')
20
22
  end
21
23
 
22
- def der_to_value(der, ber:false)
24
+ def der_to_value(der, ber: false)
23
25
  super
24
26
  check_characters
25
27
  end
26
28
 
27
29
  def check_characters
28
- if @value.to_s =~ /([^0-9 ])/
29
- raise ASN1Error, "NUMERIC STRING #@name: invalid character: '#{$1}'"
30
- end
30
+ raise ASN1Error, "NUMERIC STRING #{@name}: invalid character: '#{$1}'" if @value.to_s =~ /([^0-9 ])/
31
31
  end
32
32
  end
33
33
  end
@@ -1,77 +1,47 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RASN1
2
4
  module Types
3
-
4
5
  # ASN.1 Object ID
5
6
  # @author Sylvain Daubert
6
7
  class ObjectId < Primitive
7
- TAG = 6
8
+ # ObjectId id value
9
+ ID = 6
8
10
 
9
11
  private
10
12
 
11
13
  def value_to_der
12
- ids = @value.split('.').map! { |str| str.to_i }
14
+ ids = @value.split('.').map!(&:to_i)
13
15
 
14
- if ids[0] > 2
15
- raise ASN1Error, 'OBJECT ID #@name: first subidentifier should be less than 3'
16
- end
17
- if ids[0] < 2 and ids[1] > 39
18
- raise ASN1Error, 'OBJECT ID #@name: second subidentifier should be less than 40'
19
- end
16
+ raise ASN1Error, "OBJECT ID #{@name}: first subidentifier should be less than 3" if ids[0] > 2
17
+ raise ASN1Error, "OBJECT ID #{@name}: second subidentifier should be less than 40" if (ids[0] < 2) && (ids[1] > 39)
20
18
 
21
19
  ids[0, 2] = ids[0] * 40 + ids[1]
22
20
  ids.map! do |v|
23
21
  next v if v < 128
24
22
 
25
- ary = []
26
- while v > 0
27
- ary.unshift (v & 0x7f) | 0x80
28
- v >>= 7
29
- end
30
- ary[-1] &= 0x7f
31
- ary
23
+ unsigned_to_chained_octets(v)
32
24
  end
33
25
  ids.flatten.pack('C*')
34
26
  end
35
27
 
36
28
  def der_to_value(der, ber: false)
37
29
  bytes = der.unpack('C*')
38
- ids = if bytes[0] < 80
39
- remove = 1
40
- [ bytes[0] / 40, bytes[0] % 40]
41
- elsif bytes[0] < 128
42
- remove = 1
43
- [2, bytes[0] - 80]
44
- else
45
- remove = 1
46
- second_id = bytes[0] & 0x7f
47
- bytes[1..-1].each do |byte|
48
- remove += 1
49
- second_id <<= 7
50
- if byte < 128
51
- second_id |= byte
52
- break
53
- else
54
- second_id |= byte & 0x7f
55
- end
56
- end
57
- [2, second_id - 80]
58
- end
59
30
 
60
- id = 0
61
- bytes.shift(remove)
31
+ ids = []
32
+ current_id = 0
62
33
  bytes.each do |byte|
63
- if byte < 128
64
- if id == 0
65
- ids << byte
66
- else
67
- ids << ((id << 7) | byte)
68
- id = 0
69
- end
70
- else
71
- id = (id << 7) | (byte & 0x7f)
34
+ current_id = (current_id << 7) | (byte & 0x7f)
35
+ if (byte & 0x80).zero?
36
+ ids << current_id
37
+ current_id = 0
72
38
  end
73
39
  end
74
40
 
41
+ first_id = [2, ids.first / 40].min
42
+ second_id = ids.first - first_id * 40
43
+ ids[0..0] = [first_id, second_id]
44
+
75
45
  @value = ids.join('.')
76
46
  end
77
47
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RASN1
2
4
  module Types
3
-
4
5
  # ASN.1 Octet String
5
6
  #
6
7
  # An OCTET STRINT may contain another primtive object:
@@ -11,13 +12,12 @@ module RASN1
11
12
  # os.to_der # => DER string with INTEGER in OCTET STRING
12
13
  # @author Sylvain Daubert
13
14
  class OctetString < Primitive
14
- TAG = 0x04
15
+ # OctetString id value
16
+ ID = 4
15
17
 
16
18
  def inspect(level=0)
17
- str = ''
18
- str << ' ' * level if level > 0
19
- str << "#{@name} " unless @name.nil?
20
- str << "#{type}: #{value.inspect}"
19
+ str = common_inspect(level)
20
+ str << " #{value.inspect}"
21
21
  end
22
22
  end
23
23
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RASN1
2
4
  module Types
3
-
4
5
  # @abstract This class SHOULD be used as base class for all ASN.1 primitive
5
6
  # types.
6
7
  # @author Sylvain Daubert
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RASN1
2
4
  module Types
3
-
4
5
  # ASN.1 Printable String
5
6
  # @author Sylvain Daubert
6
7
  class PrintableString < OctetString
7
- TAG = 19
8
+ # PrintableString id value
9
+ ID = 19
8
10
 
9
11
  # Get ASN.1 type
10
12
  # @return [String]
@@ -13,21 +15,20 @@ module RASN1
13
15
  end
14
16
 
15
17
  private
16
-
18
+
17
19
  def value_to_der
18
20
  check_characters
19
21
  @value.to_s.force_encoding('BINARY')
20
22
  end
21
23
 
22
- def der_to_value(der, ber:false)
24
+ def der_to_value(der, ber: false)
23
25
  super
24
26
  check_characters
25
27
  end
26
28
 
27
29
  def check_characters
28
- if @value.to_s =~ /([^a-zA-Z0-9 '=\(\)\+,\-\.\/:\?])/
29
- raise ASN1Error, "PRINTABLE STRING #@name: invalid character: '#{$1}'"
30
- end
30
+ m = @value.to_s.match(%r{([^a-zA-Z0-9 '=()+,\-./:?])})
31
+ raise ASN1Error, "PRINTABLE STRING #{@name}: invalid character: '#{m[1]}'" if m
31
32
  end
32
33
  end
33
34
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RASN1
2
4
  module Types
3
-
4
5
  # ASN.1 sequence
5
6
  #
6
7
  # A sequence is a collection of another ASN.1 types.
@@ -25,7 +26,8 @@ module RASN1
25
26
  # seq.value # => String
26
27
  # @author Sylvain Daubert
27
28
  class Sequence < Constructed
28
- TAG = 0x10
29
+ # Sequence id value
30
+ ID = 0x10
29
31
 
30
32
  # @see Base#initialize
31
33
  def initialize(value_or_options={}, options={})
@@ -35,7 +37,19 @@ module RASN1
35
37
 
36
38
  def initialize_copy(other)
37
39
  super
38
- @value = @value.map { |v| v.dup }
40
+ @value = @value.map(&:dup)
41
+ end
42
+
43
+ # Get element at index +idx+, or element of name +name+
44
+ # @param [Integer, String, Symbol] idx_or_name
45
+ # @return [Object]
46
+ def [](idx_or_name)
47
+ case idx_or_name
48
+ when Integer
49
+ @value[idx]
50
+ when String, Symbol
51
+ @value.find { |elt| elt.name == idx_or_name }
52
+ end
39
53
  end
40
54
 
41
55
  private
@@ -43,14 +57,14 @@ module RASN1
43
57
  def value_to_der
44
58
  case @value
45
59
  when Array
46
- @value.map { |element| element.to_der }.join
60
+ @value.map(&:to_der).join
47
61
  else
48
62
  @value.to_s
49
63
  end
50
64
  end
51
65
 
52
- def der_to_value(der, ber:false)
53
- if @value.is_a?(Array) and !@value.empty?
66
+ def der_to_value(der, ber: false)
67
+ if @value.is_a?(Array) && !@value.empty?
54
68
  nb_bytes = 0
55
69
  @value.each do |element|
56
70
  nb_bytes += element.parse!(der[nb_bytes..-1])
@@ -58,7 +72,7 @@ module RASN1
58
72
  else
59
73
  @value = der
60
74
  der.length
61
- end
75
+ end
62
76
  end
63
77
  end
64
78
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RASN1
2
4
  module Types
3
-
4
5
  # ASN.1 SEQUENCE OF
5
6
  #
6
7
  # A SEQUENCE OF is an array of one ASN.1 type.
@@ -45,7 +46,8 @@ module RASN1
45
46
  # seqof[0][:int].value # => 12
46
47
  # @author Sylvain Daubert
47
48
  class SequenceOf < Constructed
48
- TAG = Sequence::TAG
49
+ # SequenceOf id value
50
+ ID = Sequence::ID
49
51
 
50
52
  # @return [Class, Base]
51
53
  attr_reader :of_type
@@ -68,7 +70,7 @@ module RASN1
68
70
  def initialize_copy(other)
69
71
  super
70
72
  @of_type = @of_type.dup
71
- @value = @value.map { |v| v.dup }
73
+ @value = @value.map(&:dup)
72
74
  end
73
75
 
74
76
  # Add an item to SEQUENCE OF
@@ -76,9 +78,11 @@ module RASN1
76
78
  def <<(obj)
77
79
  if of_type_class < Primitive
78
80
  raise ASN1Error, 'object to add should be an Array' unless obj.is_a?(Array)
81
+
79
82
  @value += obj.map { |item| @of_type.new(item) }
80
83
  elsif composed_of_type?
81
84
  raise ASN1Error, 'object to add should be an Array' unless obj.is_a?(Array)
85
+
82
86
  new_value = of_type_class.new
83
87
  @of_type.value.each_with_index do |type, i|
84
88
  type2 = type.dup
@@ -112,17 +116,15 @@ module RASN1
112
116
  end
113
117
 
114
118
  def inspect(level=0)
115
- str = ''
116
- str << ' ' * level if level > 0
117
- str << "#{@name} " unless @name.nil?
118
- level = level.abs
119
- str << "#{type}:\n"
120
- level += 1
119
+ str = common_inspect(level)
120
+ str << "\n"
121
+ level = level.abs + 1
121
122
  @value.each do |item|
122
123
  case item
123
124
  when Base, Model
124
- next if item.optional? and item.value.nil?
125
- str << "#{item.inspect(level)}"
125
+ next if item.optional? && item.value.nil?
126
+
127
+ str << item.inspect(level)
126
128
  str << "\n" unless str.end_with?("\n")
127
129
  else
128
130
  str << ' ' * level + "#{item.inspect}\n"
@@ -142,10 +144,10 @@ module RASN1
142
144
  end
143
145
 
144
146
  def value_to_der
145
- @value.map { |v| v.to_der }.join
147
+ @value.map(&:to_der).join
146
148
  end
147
149
 
148
- def der_to_value(der, ber:false)
150
+ def der_to_value(der, ber: false)
149
151
  @value = []
150
152
  nb_bytes = 0
151
153
 
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RASN1
2
4
  module Types
3
-
4
5
  # ASN.1 set
5
6
  #
6
7
  # A set is a collection of another ASN.1 types.
@@ -20,7 +21,8 @@ module RASN1
20
21
  # ]
21
22
  # @author Sylvain Daubert
22
23
  class Set < Sequence
23
- TAG = 0x11
24
+ # Set id value
25
+ ID = 0x11
24
26
  end
25
27
  end
26
28
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RASN1
2
4
  module Types
3
-
4
5
  # ASN.1 SET OF
5
6
  # @author Sylvain Daubert
6
7
  class SetOf < SequenceOf
7
- TAG = Set::TAG
8
+ # SetOf id value
9
+ ID = Set::ID
8
10
 
9
11
  # A SET OF is encoded as a SET.
10
12
  # @return ['SET']
@@ -14,4 +16,3 @@ module RASN1
14
16
  end
15
17
  end
16
18
  end
17
-
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'date'
2
4
 
3
5
  module RASN1
4
6
  module Types
5
-
6
7
  # ASN.1 UTCTime
7
8
  #
8
9
  # +{#value} of a +UtcTime+ should be a ruby Time.
@@ -17,7 +18,8 @@ module RASN1
17
18
  # not.
18
19
  # @author Sylvain Daubert
19
20
  class UtcTime < Primitive
20
- TAG = 23
21
+ # UtcTime id value
22
+ ID = 23
21
23
 
22
24
  # Get ASN.1 type
23
25
  # @return [String]
@@ -26,11 +28,11 @@ module RASN1
26
28
  end
27
29
 
28
30
  private
29
-
31
+
30
32
  def value_to_der
31
33
  @value.getutc.strftime('%y%m%d%H%M%SZ')
32
34
  end
33
-
35
+
34
36
  def der_to_value(der, ber: false)
35
37
  format = case der.size
36
38
  when 11