rasn1 0.16.2 → 0.17.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.
@@ -10,32 +10,44 @@ module RASN1
10
10
  module Types
11
11
  # A ASN.1 CHOICE is a choice between different types.
12
12
  #
13
- # == Create a CHOICE
14
- # A CHOICE is defined this way:
13
+ # @example Create a CHOICE
15
14
  # choice = Choice.new
16
15
  # choice.value = [Integer.new(implicit: 0, class: :context),
17
16
  # Integer.new(implicit: 1, class: :context),
18
17
  # OctetString.new(implicit: 2, class: :context)]
19
- # The chosen type may be set this way:
20
- # choice.chosen = 0 # choose :int1
21
- # The chosen value may be set these ways:
18
+ # # Choose an element
19
+ # choice.chosen = 0 # choose int1
20
+ # # Set chosen value
22
21
  # choise.value[choice.chosen].value = 1
23
- # choise.set_chosen_value 1
24
- # The chosen value may be got these ways:
22
+ # # Also set chosen value
23
+ # choise.set_chosen_value(1)
24
+ # # Got chosen value
25
25
  # choise.value[choice.chosen].value # => 1
26
26
  # choice.chosen_value # => 1
27
27
  #
28
- # == Encode a CHOICE
29
- # {#to_der} only encodes the chosen value:
30
- # choise.to_der # => "\x80\x01\x01"
28
+ # @example Encode a CHOICE
29
+ # choice = Choice.new
30
+ # choice.value = [Integer.new(implicit: 0, class: :context, value: 1),
31
+ # Integer.new(implicit: 1, class: :context),
32
+ # OctetString.new(implicit: 2, class: :context, value: "a")]
33
+ # # to_der only encodes the chosen value
34
+ # choice.chosen = 0 # choose int1
35
+ # choice.to_der # => "\x80\x01\x01"
36
+ # # another choice, another encoding string
37
+ # choice.chosen_value = 2
38
+ # choice.to_der # => "\x82\x01a"
31
39
  #
32
- # == Parse a CHOICE
33
- # Parsing a CHOICE set {#chosen} and set value to chosen type. If parsed string does
34
- # not contain a type from CHOICE, a {RASN1::ASN1Error} is raised.
35
- # str = "\x04\x03abc"
36
- # choice.parse! str
40
+ # @example Parse a CHOICE
41
+ # choice = Choice.new
42
+ # choice.value = [Integer.new(implicit: 0, class: :context, value: 1),
43
+ # Integer.new(implicit: 1, class: :context),
44
+ # OctetString.new(implicit: 2, class: :context, value: "a")]
45
+ # # Parse an octet string
46
+ # choice.parse!("\x82\x03abc")
37
47
  # choice.chosen # => 2
38
48
  # choice.chosen_value # => "abc"
49
+ # # Parse an unexpected value
50
+ # choice.parse!("\x04\x03abc") # => RASN1::ASN1Error
39
51
  # @author Sylvain Daubert
40
52
  class Choice < Base
41
53
  # Chosen type
@@ -44,7 +56,7 @@ module RASN1
44
56
 
45
57
  # Set chosen value.
46
58
  # @note {#chosen} MUST be set before calling this method
47
- # @param [Object] value
59
+ # @param value [Object]
48
60
  # @return [Object] value
49
61
  # @raise [ChoiceError] {#chosen} not set
50
62
  def set_chosen_value(value) # rubocop:disable Naming/AccessorMethodName
@@ -68,9 +80,10 @@ module RASN1
68
80
  end
69
81
  end
70
82
 
71
- # @note {#chosen} MUST be set before calling this method
83
+ # Encode Choice into DER encoding
72
84
  # @return [String] DER-formated string
73
85
  # @raise [ChoiceError] {#chosen} not set
86
+ # @note {#chosen} MUST be set before calling this method
74
87
  def to_der
75
88
  check_chosen
76
89
  @value[@chosen].to_der
@@ -78,8 +91,8 @@ module RASN1
78
91
 
79
92
  # Parse a DER string. This method updates object by setting {#chosen} and
80
93
  # chosen value.
81
- # @param [String] der DER string
82
- # @param [Boolean] ber if +true+, accept BER encoding
94
+ # @param der [String] DER string
95
+ # @param ber [Boolean] if +true+, accept BER encoding
83
96
  # @return [Integer] total number of parsed bytes
84
97
  # @raise [ASN1Error] error on parsing
85
98
  def parse!(der, ber: false)
@@ -96,6 +109,7 @@ module RASN1
96
109
  end
97
110
 
98
111
  # @private
112
+ # @!macro do_parse
99
113
  # @see Types::Base#do_parse
100
114
  # @since 0.15.0 Specific +#do_parse+ to handle recursivity
101
115
  def do_parse(der, ber: false)
@@ -115,8 +129,8 @@ module RASN1
115
129
  end
116
130
 
117
131
  # Make choice value from DER/BER string.
118
- # @param [String] der
119
- # @param [::Boolean] ber
132
+ # @param der [String]
133
+ # @param ber [::Boolean]
120
134
  # @return [void]
121
135
  # @since 0.15.0 Specific +#der_to_value+ to handle recursivity
122
136
  def der_to_value(der, ber: false)
@@ -130,7 +144,7 @@ module RASN1
130
144
  end
131
145
  end
132
146
 
133
- # @param [::Integer] level
147
+ # @param level [::Integer]
134
148
  # @return [String]
135
149
  def inspect(level=0)
136
150
  str = common_inspect(level)
@@ -148,7 +162,7 @@ module RASN1
148
162
  end
149
163
 
150
164
  # Return empty array
151
- # @return [Array()]
165
+ # @return [Array]
152
166
  # @since 0.15.0
153
167
  def void_value
154
168
  []
@@ -156,6 +170,8 @@ module RASN1
156
170
 
157
171
  private
158
172
 
173
+ # @return [void]
174
+ # @raise [ChoiceError] {#chosen} is not set
159
175
  def check_chosen
160
176
  raise ChoiceError.new(self) if !defined?(@chosen) || @chosen.nil?
161
177
  end
@@ -25,7 +25,7 @@ module RASN1
25
25
  end
26
26
 
27
27
  # Check constraint, if defined
28
- # @param [Object] value the value of the type to check
28
+ # @param value [Object] the value of the type to check
29
29
  # @raise [ConstraintError] constraint is not verified
30
30
  def check_constraint(value)
31
31
  return unless constrained?
@@ -36,6 +36,7 @@ module RASN1
36
36
  extend ClassMethods
37
37
 
38
38
  # Redefined +#value=+ to check constraint before assigning +val+
39
+ # @!macro value_setter
39
40
  # @see Types::Base#value=
40
41
  # @raise [ConstraintError] constraint is not verified
41
42
  def value=(val)
@@ -44,8 +45,8 @@ module RASN1
44
45
  end
45
46
 
46
47
  # Make value from +der+ string and check constraints
47
- # @param [String] der
48
- # @param [::Boolean] ber
48
+ # @param der [String]
49
+ # @param ber [::Boolean]
49
50
  # @return [void]
50
51
  # @raise [ConstraintError] constraint is not verified
51
52
  def der_to_value(der, ber: false)
@@ -10,7 +10,9 @@ module RASN1
10
10
  module Types
11
11
  # @abstract This class SHOULD be used as base class for all ASN.1 primitive
12
12
  # types.
13
- # Base class for all ASN.1 constructed types
13
+ # This is the base class for all ASN.1 constructed types. A constructed type combines similar or different
14
+ # {Primitive primitive} types into ordered or unordered groups
15
+ #
14
16
  # @author Sylvain Daubert
15
17
  class Constructed < Base
16
18
  # Constructed value
@@ -30,7 +32,7 @@ module RASN1
30
32
  end
31
33
  end
32
34
 
33
- # @param [::Integer] level (default: 0)
35
+ # @param level [::Integer] (default: 0)
34
36
  # @return [String]
35
37
  def inspect(level=0)
36
38
  case @value
@@ -10,18 +10,19 @@ module RASN1
10
10
  module Types
11
11
  # ASN.1 Enumerated
12
12
  #
13
- # An enumerated type permits to assign names to integer values. It may be defined
14
- # different ways:
13
+ # An ENUMERATED type permits to assign names to integer values. {Integer} may
14
+ # also be enumerated, but the tag {ID} is different.
15
+ #
16
+ # @example Example 1
15
17
  # enum = RASN1::Types::Enumerated.new(enum: { 'a' => 0, 'b' => 1, 'c' => 2 })
18
+ # enum.value = 'a'
19
+ # enum.value # => 'a'
20
+ # @example Example 2
16
21
  # enum = RASN1::Types::Enumerated.new(enum: { a: 0, b: 1, c: 2 })
17
- # Its value should be setting as an Integer or a String/symbol:
18
22
  # enum.value = :b
19
23
  # enum.value = 1 # equivalent to :b
20
- # But its value is always stored as named integer:
21
- # enum.value = :b
22
- # enum.value # => :b
23
- # enum.value = 0
24
- # enum.value # => :a
24
+ # # enum returned value is always symbolic (even if set with an integer)
25
+ # enum.value # => :b
25
26
  # A {EnumeratedError} is raised when set value is not in enumeration.
26
27
  # @author Sylvain Daubert
27
28
  class Enumerated < Integer
@@ -15,26 +15,29 @@ module RASN1
15
15
  # +{#value} of a {GeneralizedTime} should be a ruby Time.
16
16
  #
17
17
  # ===Notes
18
- # When encoding, resulting string is always a UTC time, appended with +Z+.
18
+ # On encoding, resulting string is always a UTC time, appended with +Z+.
19
19
  # Minutes and seconds are always generated. Fractions of second are generated
20
20
  # if value Time object have them.
21
21
  #
22
- # On parsing, are supported:
22
+ # On parsing, this class supports:
23
23
  # * UTC times (ending with +Z+),
24
24
  # * local times (no suffix),
25
25
  # * local times with difference between UTC and this local time (ending with
26
26
  # +sHHMM+, where +s+ is +++ or +-+, and +HHMM+ is the time differential
27
27
  # betwen UTC and local time).
28
28
  # These times may include minutes and seconds. Fractions of hour, minute and
29
- # second are supported.
29
+ # second are also supported.
30
30
  # @author Sylvain Daubert
31
+ # @author LemonTree55
31
32
  class GeneralizedTime < Primitive
32
33
  # GeneralizedTime id value
33
34
  ID = 24
34
35
 
35
36
  # @private
37
+ # Second count in one hour
36
38
  HOUR_TO_SEC = 3600
37
39
  # @private
40
+ # Second count in one minute
38
41
  MINUTE_TO_SEC = 60
39
42
  # @private
40
43
  SECOND_TO_SEC = 1
@@ -51,8 +54,8 @@ module RASN1
51
54
  end
52
55
 
53
56
  # Make time value from +der+ string
54
- # @param [String] der
55
- # @param [::Boolean] ber
57
+ # @param der [String]
58
+ # @param ber [::Boolean]
56
59
  # @return [void]
57
60
  def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
58
61
  date_hour, fraction = der.split('.')
@@ -70,6 +73,7 @@ module RASN1
70
73
 
71
74
  private
72
75
 
76
+ # @return [String]
73
77
  def value_to_der
74
78
  utc_value = @value.getutc
75
79
  if utc_value.nsec.positive?
@@ -80,6 +84,9 @@ module RASN1
80
84
  end
81
85
  end
82
86
 
87
+ # Set internal value to a Time defined from date and hour from +date_hour+, without fraction.
88
+ # @param date_hour [String]
89
+ # @return [void]
83
90
  def value_when_fraction_empty(date_hour)
84
91
  tz = compute_tz(date_hour)
85
92
  year = date_hour.slice!(0, 4).to_i
@@ -91,21 +98,21 @@ module RASN1
91
98
  @value = Time.new(year, month, day, hour, minute, second, tz)
92
99
  end
93
100
 
94
- # Ruby 3.0: special handle for timezone
95
- # From 3.1: "Z" and "-0100" are supported
96
- # Below 3.1: should be "-01:00" or "+00:00"
101
+ # Compute TZ from +date_hour+ string
102
+ # @param date_hour [String]
103
+ # @return [String]
97
104
  def compute_tz(date_hour)
98
105
  if date_hour.end_with?('Z')
99
106
  date_hour.slice!(-1, 1)
100
- '+00:00' # Ruby 3.0: to remove after end-of support of ruby 3.0
101
107
  elsif date_hour.match?(/[+-]\d+$/)
102
- # Ruby 3.0
103
- # date_hour.slice!(-5, 5)
104
- zone = date_hour.slice!(-5, 5).to_s
105
- "#{zone[0, 3]}:#{zone[3, 2]}"
108
+ date_hour.slice!(-5, 5)
106
109
  end
107
110
  end
108
111
 
112
+ # Set value in special case where fraction ends with 'Z'
113
+ # @param date_hour [String]
114
+ # @param fraction [String]
115
+ # @return [void]
109
116
  def value_when_fraction_ends_with_z(date_hour, fraction)
110
117
  fraction = fraction[0...-1]
111
118
  date_hour << 'Z'
@@ -114,6 +121,10 @@ module RASN1
114
121
  fix_value(fraction, frac_base)
115
122
  end
116
123
 
124
+ # Set value in general case
125
+ # @param date_hour [String]
126
+ # @param fraction [String]
127
+ # @return [void]
117
128
  def value_on_others_cases(date_hour, fraction)
118
129
  match = fraction.match(/(\d+)([+-]\d+)/)
119
130
  if match
@@ -127,11 +138,18 @@ module RASN1
127
138
  fix_value(fraction, frac_base)
128
139
  end
129
140
 
141
+ # Fix internal value with +fraction+, based on +frac_base+
142
+ # @param fraction [String]
143
+ # @param frac_base [::Integer]
144
+ # @return [void]
130
145
  def fix_value(fraction, frac_base)
131
146
  frac = ".#{fraction}".to_r * frac_base
132
147
  @value = (@value + frac) unless fraction.nil?
133
148
  end
134
149
 
150
+ # Compute fraction base from +date_hour+ string
151
+ # @param date_hour [String]
152
+ # @return [::Integer]
135
153
  def compute_frac_base(date_hour)
136
154
  case date_hour.size
137
155
  when 10, 11
@@ -152,6 +170,7 @@ module RASN1
152
170
  end
153
171
  end
154
172
 
173
+ # @return [String]
155
174
  def trace_data
156
175
  return super if explicit?
157
176
 
@@ -9,25 +9,50 @@
9
9
  module RASN1
10
10
  module Types
11
11
  # ASN.1 Integer
12
+ #
13
+ # An INTEGER is a primitive type to represent integers.
14
+ # There is no limit on integer size.
15
+ #
16
+ # @example Simple Integers
17
+ # # Simple integer with a value associated
18
+ # int1 = RASN1::Types::Integer.new(value: 42)
19
+ # # Integer without value, but a default one
20
+ # int2 = RASN1::Types::Integer.new(default: -42)
21
+ #
22
+ # @example Enumerated Integer
23
+ # enum = RASN1::Types::Integer.new(enum: {one: 1, two: 2})
24
+ # enum.value = :two
25
+ # enum.value #=> :two
26
+ # enum.to_i #=> 2
12
27
  # @author Sylvain Daubert
28
+ # @author LemonTree55
13
29
  class Integer < Primitive
14
- # @return [Hash,nil]
30
+ # Associated enumeration
31
+ # @return [Hash{String=>::Integer},nil]
15
32
  attr_reader :enum
16
33
 
17
34
  # Integer id value
18
35
  ID = 2
19
36
 
20
- # @option options [Hash] :enum enumeration hash. Keys are names, and values
37
+ # @!macro type_initialize
38
+ # @option options [Hash{String=>::Integer}] :enum enumeration hash. Keys are names, and values
21
39
  # are integers.
22
40
  # @raise [EnumeratedError] +:default+ value is unknown when +:enum+ key is present
23
- # @see Base#initialize common options to all ASN.1 types
24
41
  def initialize(options={})
25
42
  super
26
43
  initialize_enum(@options[:enum])
27
44
  end
28
45
 
29
- # @param [Integer,String,Symbol,nil] val
46
+ # Set integer value from a Ruby integer, or a String or a Symbol (only when {#enum} is defined).
47
+ # @param val [::Integer,String,Symbol,nil]
30
48
  # @return [void]
49
+ # @note
50
+ # An enumerated INTEGER may be set with an integer value out of enumeration,
51
+ # only when no value is set.
52
+ # @raise [EnumeratedError] string/symbol value: no enum defined or +val+ not in enum
53
+ # @raise [EnumeratedError] integer value: value already set and new value not in enum
54
+ # @raise [TypeError] unsupported +val+ type
55
+ # @since 0.16.2 raise TypeError (was EnumeratedError)
31
56
  def value=(val)
32
57
  @no_value = false
33
58
  case val
@@ -39,17 +64,17 @@ module RASN1
39
64
  @no_value = true
40
65
  @value = void_value
41
66
  else
42
- raise EnumeratedError, "#{@name}: not in enumeration"
67
+ raise TypeError, "#{val.class} not supported"
43
68
  end
44
69
  end
45
70
 
46
- # @return [Integer]
71
+ # @return [::Integer]
47
72
  def void_value
48
73
  0
49
74
  end
50
75
 
51
76
  # Integer value
52
- # @return [Integer]
77
+ # @return [::Integer]
53
78
  def to_i
54
79
  val = value? ? @value : @default
55
80
  case val
@@ -61,8 +86,8 @@ module RASN1
61
86
  end
62
87
 
63
88
  # Make integer value from +der+ string.
64
- # @param [String] der
65
- # @param [::Boolean] ber
89
+ # @param der [String]
90
+ # @param ber [::Boolean]
66
91
  # @return [void]
67
92
  def der_to_value(der, ber: false)
68
93
  int_value = der_to_int_value(der, ber: ber)
@@ -75,6 +100,9 @@ module RASN1
75
100
 
76
101
  private
77
102
 
103
+ # Initialize integer with given enum hash.
104
+ # @param enum [Hash{String=>::Integer}]
105
+ # @return [void]
78
106
  def initialize_enum(enum)
79
107
  @enum = enum || {}
80
108
  return if @enum.empty?
@@ -85,6 +113,10 @@ module RASN1
85
113
  check_enum_default
86
114
  end
87
115
 
116
+ # Check defined default is coherent with enum
117
+ # @return [void]
118
+ # @raise [EnumeratedError] default value not defined in {#enum}
119
+ # @raise [TypeError] unsupported type for default value
88
120
  def check_enum_default
89
121
  case @default
90
122
  when String, Symbol
@@ -99,6 +131,10 @@ module RASN1
99
131
  end
100
132
  end
101
133
 
134
+ # Set value from given string or symbol value
135
+ # @param val [String,Symbol]
136
+ # @return [void]
137
+ # @raise [EnumeratedError] no enum defined or +val+ not in enum
102
138
  def value_from_string_or_symbol(val)
103
139
  raise EnumeratedError, "#{@name} has no :enum" if @enum.empty?
104
140
  raise EnumeratedError, "#{@name}: unknwon enumerated value #{val}" unless @enum.key? val
@@ -106,6 +142,10 @@ module RASN1
106
142
  @value = val
107
143
  end
108
144
 
145
+ # Set value from given integer value.
146
+ # @param val [::Integer]
147
+ # @return [void]
148
+ # @raise [EnumeratedError] +val+ not in enum
109
149
  def value_from_integer(val)
110
150
  if @enum.empty?
111
151
  @value = val
@@ -116,6 +156,8 @@ module RASN1
116
156
  end
117
157
  end
118
158
 
159
+ # @param value [::Integer]
160
+ # @return [String]
119
161
  def int_value_to_der(value)
120
162
  size = compute_size(value)
121
163
  comp_value = value >= 0 ? value : (~(-value) + 1) & ((1 << (size * 8)) - 1)
@@ -125,12 +167,16 @@ module RASN1
125
167
  ary.reverse.pack('C*')
126
168
  end
127
169
 
170
+ # Get size in bytes of +value+ integer
171
+ # @param value [::Integer]
172
+ # @return [::Integer]
128
173
  def compute_size(value)
129
174
  size = value.bit_length / 8 + ((value.bit_length % 8).positive? ? 1 : 0)
130
175
  size = 1 if size.zero?
131
176
  size
132
177
  end
133
178
 
179
+ # @return [String]
134
180
  def value_to_der
135
181
  case @value
136
182
  when String, Symbol
@@ -142,6 +188,9 @@ module RASN1
142
188
  end
143
189
  end
144
190
 
191
+ # @param der [String]
192
+ # @param ber [::Boolean]
193
+ # @return [::Integer]
145
194
  def der_to_int_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
146
195
  ary = der.unpack('C*')
147
196
  v = ary.reduce(0) { |len, b| (len << 8) | b }
@@ -149,22 +198,29 @@ module RASN1
149
198
  v
150
199
  end
151
200
 
201
+ # Return value to show (enumerated if enum is defined, else integer)
202
+ # @param int [::Integer]
203
+ # @param check_enum [::Boolean]
204
+ # @return [String,::Integer]
205
+ # @raise [EnumeratedError] +check_enum+ is +true+, enum is defined, and +int+ is not in enum
152
206
  def int_to_enum(int, check_enum: true)
153
207
  raise EnumeratedError, "#{@name}: value #{int} not in enumeration" if check_enum && !@enum.value?(int)
154
208
 
155
209
  @enum.key(int) || int
156
210
  end
157
211
 
212
+ # @return [::Integer]
158
213
  def explicit_type
159
214
  self.class.new(name: name, enum: enum)
160
215
  end
161
216
 
217
+ # @return [String]
162
218
  def trace_data
163
219
  return super if explicit?
164
- return " #{der_to_int_value(raw_data)} (0x#{raw_data.unpack1('H*')})" if @enum.empty?
220
+ return " #{der_to_int_value(raw_data)} (0x#{bin2hex(raw_data)})" if @enum.empty?
165
221
 
166
222
  v = int_to_enum(der_to_int_value(raw_data), check_enum: false)
167
- " #{v} (0x#{raw_data.unpack1('H*')})"
223
+ " #{v} (0x#{bin2hex(raw_data)})"
168
224
  end
169
225
  end
170
226
  end
@@ -9,11 +9,14 @@
9
9
  module RASN1
10
10
  module Types
11
11
  # ASN.1 Null
12
+ #
13
+ # This type is a placeholder when a value is not mandatory (in a {Choice}, by example).
12
14
  # @author Sylvain Daubert
13
15
  class Null < Primitive
14
16
  # Null id value
15
17
  ID = 0x05
16
18
 
19
+ # @param level [Integer]
17
20
  # @return [String]
18
21
  def inspect(level=0)
19
22
  str = common_inspect(level)[0..-2] # remove terminal ':'
@@ -21,15 +24,15 @@ module RASN1
21
24
  str
22
25
  end
23
26
 
24
- # @return [Boolean]
25
27
  # Build only if not optional
28
+ # @return [Boolean]
26
29
  def can_build?
27
30
  !optional?
28
31
  end
29
32
 
30
33
  # Check +der+ string
31
- # @param [String] der
32
- # @param [::Boolean] ber
34
+ # @param der [String]
35
+ # @param ber [::Boolean]
33
36
  # @return [void]
34
37
  # @raise [ASN1Error] +der+ is not empty
35
38
  def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
@@ -41,6 +44,7 @@ module RASN1
41
44
 
42
45
  private
43
46
 
47
+ # @return [String]
44
48
  def value_to_der
45
49
  ''
46
50
  end
@@ -9,7 +9,14 @@
9
9
  module RASN1
10
10
  module Types
11
11
  # ASN.1 Numeric String
12
+ #
13
+ # A NUMERIC STRING is an {OctetString} limited to numeric digit.
14
+ # @example Numeric string
15
+ # ns = RASN1::Types::NumrericString.new(value: "123")
16
+ # ns.to_der #=> "\x12\x03123"
17
+ # RASN1.parse(ns.to_der).value #=> "123"
12
18
  # @author Sylvain Daubert
19
+ # @author LemonTree55
13
20
  class NumericString < OctetString
14
21
  # NumericString id value
15
22
  ID = 18
@@ -23,10 +30,11 @@ module RASN1
23
30
  end
24
31
 
25
32
  # Make string value from +der+ string
26
- # @param [String] der
27
- # @param [::Boolean] ber
33
+ # @param der [String]
34
+ # @param ber [::Boolean]
28
35
  # @return [void]
29
36
  # @raise [ASN1Error] invalid characters detected
37
+ # @raise [ASN1Error] invalid character in string
30
38
  def der_to_value(der, ber: false)
31
39
  super
32
40
  check_characters
@@ -34,11 +42,15 @@ module RASN1
34
42
 
35
43
  private
36
44
 
45
+ # @return [String]
46
+ # @raise [ASN1Error] invalid character in string
37
47
  def value_to_der
38
48
  check_characters
39
49
  @value.to_s.b
40
50
  end
41
51
 
52
+ # @return [void]
53
+ # @raise [ASN1Error] invalid character in string
42
54
  def check_characters
43
55
  raise ASN1Error, "NUMERIC STRING #{@name}: invalid character: '#{$1}'" if @value.to_s =~ INVALID_CHARS
44
56
  end
@@ -9,6 +9,15 @@
9
9
  module RASN1
10
10
  module Types
11
11
  # ASN.1 Object ID
12
+ #
13
+ # An OBJECT ID provides unique identifiers.
14
+ #
15
+ # Object Id are shown as numbered dotted strings, like +0.1.2.1256.1+. First number is in range [0-2], the second
16
+ # in range [0-39]. Others are not limited.
17
+ #
18
+ # @example Object id
19
+ # oid = RASN1::Types::ObjectId.new(value: "0.2.145.65589.1")
20
+ # oid.to_der #=> "\x06\a\x02\x81\x11\x84\x805\x01"
12
21
  # @author Sylvain Daubert
13
22
  # @author LemonTree55
14
23
  class ObjectId < Primitive
@@ -16,8 +25,8 @@ module RASN1
16
25
  ID = 6
17
26
 
18
27
  # Make object id value from +der+ string
19
- # @param [String] der
20
- # @param [::Boolean] ber
28
+ # @param der [String]
29
+ # @param ber [::Boolean]
21
30
  # @return [void]
22
31
  def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
23
32
  bytes = der.unpack('C*')
@@ -41,6 +50,7 @@ module RASN1
41
50
 
42
51
  private
43
52
 
53
+ # @return [String]
44
54
  # @raise [ASN1Error]
45
55
  def value_to_der
46
56
  ids = @value.to_s.split('.').map(&:to_i)
@@ -59,8 +69,9 @@ module RASN1
59
69
  octets.pack('C*')
60
70
  end
61
71
 
62
- # @param [Array[::Integer]] ids
63
- # @raise [ASN1Error]
72
+ # @param ids [Array<::Integer>]
73
+ # @return [void]
74
+ # @raise [ASN1Error] one in two first ids are out of range
64
75
  def check_first_ids(ids)
65
76
  raise ASN1Error, "OBJECT ID #{@name}: first subidentifier should be less than 3" if ids[0] > 2
66
77
  raise ASN1Error, "OBJECT ID #{@name}: second subidentifier should be less than 40" if (ids[0] < 2) && (ids[1] > 39)
@@ -21,7 +21,7 @@ module RASN1
21
21
  # OctetString id value
22
22
  ID = 4
23
23
 
24
- # @param [::Integer] level
24
+ # @param level [::Integer]
25
25
  # @return [String]
26
26
  def inspect(level=0)
27
27
  str = common_inspect(level)
@@ -29,8 +29,8 @@ module RASN1
29
29
  end
30
30
 
31
31
  # Make string value from +der+ string. Force encoding to UTF-8
32
- # @param [String] der
33
- # @param [::Boolean] ber
32
+ # @param der [String]
33
+ # @param ber [::Boolean]
34
34
  # @return [void]
35
35
  # @since 0.15.0 Handle ENCODING constant, if defined by subclass
36
36
  def der_to_value(der, ber: false)