rasn1 0.5.0 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e9f8ffeb57fd641930cbe2e820c903102ed404e6
4
- data.tar.gz: 8d214577ea3085f99a96926e9e26a81f3148e262
3
+ metadata.gz: 38f025ab48cabca987b7e0813332e9228ab1933a
4
+ data.tar.gz: 84ed306ccd84238b89ea1e02f2b73a9bf8558f41
5
5
  SHA512:
6
- metadata.gz: c6a96e1e65a1fccaa036b984933fda1b3f5c43d03c0a6b05fb262b3b2a3a1cf6aebb4de0e87bf38455ea726f1a21ec793e307dfe24dd94b202ef0428b7db79dd
7
- data.tar.gz: cbad3dcc907ef35b8bb6689fa4d35b04797c2374f7e9a7f9b26349b0da3bdb99ec71b7262c3018104175d64b9d3922bd0d8564b194f2616f3a02c60415ea631b
6
+ metadata.gz: a3b4edc322d49eb3e68ecccada5e5022c7f0d08e183a71b991faf62b488c6e70753e531e0a7b5d7bce6bf0a9f4a41da74162f476631097abfd42631962856529
7
+ data.tar.gz: 6144b8db2f536adc0f8d0f61727724b556058fadd14f02666d5f91df8dfd7f0b92a93a2e30c4a51526a61d6997f3b102e8a2b876d2fc74556190e8cf512854cf
data/.travis.yml CHANGED
@@ -4,6 +4,6 @@ rvm:
4
4
  - 2.3.4
5
5
  - 2.4.1
6
6
  install:
7
- - bundler install --path vendor/bundle --jobs=3 --retry=3
7
+ - bundle install --path vendor/bundle --jobs=3 --retry=3
8
8
  script:
9
- - bundler exec rake
9
+ - bundle exec rake
data/lib/rasn1.rb CHANGED
@@ -29,4 +29,35 @@ module RASN1
29
29
  "CHOICE #@name: #chosen not set"
30
30
  end
31
31
  end
32
+
33
+ # Parse a DER/BER string without checking a model
34
+ # @note If you want to check ASN.1 grammary, you should define a {Model}
35
+ # and use {Model#parse}.
36
+ # @note This method will never decode SEQUENCE OF or SET OF objects, as these
37
+ # ones use the same encoding as SEQUENCE and SET, respectively.
38
+ # @note Real type of tagged value cannot be guessed. So, such tag will
39
+ # generate {Types::Base} objects.
40
+ # @param [String] der binary string to parse
41
+ # @param [Boolean] ber if +true+, decode a BER string, else a DER one
42
+ # @return [Types::Base]
43
+ def self.parse(der, ber: false)
44
+ root = nil
45
+ while der.size > 0
46
+ type = Types.tag2type(der[0].ord)
47
+ type.parse!(der, ber: ber)
48
+ root = type if root.nil?
49
+
50
+ if [Types::Sequence, Types::Set].include? type.class
51
+ subder = type.value
52
+ ary = []
53
+ while subder.size > 0
54
+ ary << self.parse(subder)
55
+ subder = subder[ary.last.to_der.size..-1]
56
+ end
57
+ type.value = ary
58
+ end
59
+ der = der[type.to_der.size..-1]
60
+ end
61
+ root
62
+ end
32
63
  end
data/lib/rasn1/model.rb CHANGED
@@ -95,15 +95,22 @@ module RASN1
95
95
  end
96
96
 
97
97
  # @method sequence(name, options)
98
+ # @param [Symbol,String] name name of object in model
99
+ # @param [Hash] options
98
100
  # @see Types::Sequence#initialize
99
101
  # @method set(name, options)
102
+ # @param [Symbol,String] name name of object in model
103
+ # @param [Hash] options
100
104
  # @see Types::Set#initialize
101
105
  # @method choice(name, options)
106
+ # @param [Symbol,String] name name of object in model
107
+ # @param [Hash] options
102
108
  # @see Types::Choice#initialize
103
109
  %w(sequence set choice).each do |type|
104
110
  class_eval "def #{type}(name, options={})\n" \
111
+ " options.merge!(name: name)\n" \
105
112
  " proc = Proc.new do |opts|\n" \
106
- " Types::#{type.capitalize}.new(name, options.merge(opts))\n" \
113
+ " Types::#{type.capitalize}.new(options.merge(opts))\n" \
107
114
  " end\n" \
108
115
  " @root = [name, proc]\n" \
109
116
  " @root << options[:content] unless options[:content].nil?\n" \
@@ -112,54 +119,82 @@ module RASN1
112
119
  end
113
120
 
114
121
  # @method sequence_of(name, type, options)
122
+ # @param [Symbol,String] name name of object in model
123
+ # @param [Model, Types::Base] type type for SEQUENCE OF
124
+ # @param [Hash] options
115
125
  # @see Types::SequenceOf#initialize
116
126
  # @method set_of(name, type, options)
127
+ # @param [Symbol,String] name name of object in model
128
+ # @param [Model, Types::Base] type type for SET OF
129
+ # @param [Hash] options
117
130
  # @see Types::SetOf#initialize
118
131
  %w(sequence set).each do |type|
119
132
  klass_name = "Types::#{type.capitalize}Of"
120
133
  class_eval "def #{type}_of(name, type, options={})\n" \
134
+ " options.merge!(name: name)\n" \
121
135
  " proc = Proc.new do |opts|\n" \
122
- " #{klass_name}.new(name, type, options.merge(opts))\n" \
136
+ " #{klass_name}.new(type, options.merge(opts))\n" \
123
137
  " end\n" \
124
138
  " @root = [name, proc]\n" \
125
139
  "end"
126
140
  end
127
141
 
128
142
  # @method boolean(name, options)
143
+ # @param [Symbol,String] name name of object in model
144
+ # @param [Hash] options
129
145
  # @see Types::Boolean#initialize
130
146
  # @method integer(name, options)
147
+ # @param [Symbol,String] name name of object in model
148
+ # @param [Hash] options
131
149
  # @see Types::Integer#initialize
132
150
  # @method bit_string(name, options)
151
+ # @param [Symbol,String] name name of object in model
152
+ # @param [Hash] options
133
153
  # @see Types::BitString#initialize
134
154
  # @method octet_string(name, options)
155
+ # @param [Symbol,String] name name of object in model
156
+ # @param [Hash] options
135
157
  # @see Types::OctetString#initialize
136
158
  # @method null(name, options)
159
+ # @param [Symbol,String] name name of object in model
160
+ # @param [Hash] options
137
161
  # @see Types::Null#initialize
138
162
  # @method enumerated(name, options)
163
+ # @param [Symbol,String] name name of object in model
164
+ # @param [Hash] options
139
165
  # @see Types::Enumerated#initialize
140
166
  # @method utf8_string(name, options)
167
+ # @param [Symbol,String] name name of object in model
168
+ # @param [Hash] options
141
169
  # @see Types::Utf8String#initialize
142
170
  Types.primitives.each do |prim|
143
171
  next if prim == Types::ObjectId
144
172
  class_eval "def #{prim.type.downcase.gsub(/\s+/, '_')}(name, options={})\n" \
173
+ " options.merge!(name: name)\n" \
145
174
  " proc = Proc.new do |opts|\n" \
146
- " #{prim.to_s}.new(name, options.merge(opts))\n" \
175
+ " #{prim.to_s}.new(options.merge(opts))\n" \
147
176
  " end\n" \
148
177
  " @root = [name, proc]\n" \
149
178
  "end"
150
179
  end
151
180
 
181
+ # @param [Symbol,String] name name of object in model
182
+ # @param [Hash] options
152
183
  # @note This method is named +objectid+ and not +object_id+ to not override
153
184
  # +Object#object_id+.
154
185
  # @see Types::ObjectId#initialize
155
186
  def objectid(name, options={})
156
- proc = Proc.new { |opts| Types::ObjectId.new(name, options.merge(opts)) }
187
+ options.merge!(name: name)
188
+ proc = Proc.new { |opts| Types::ObjectId.new(options.merge(opts)) }
157
189
  @root = [name, proc]
158
190
  end
159
191
 
192
+ # @param [Symbol,String] name name of object in model
193
+ # @param [Hash] options
160
194
  # @see Types::Any#initialize
161
195
  def any(name, options={})
162
- proc = Proc.new { |opts| Types::Any.new(name, options.merge(opts)) }
196
+ options.merge!(name: name)
197
+ proc = Proc.new { |opts| Types::Any.new(options.merge(opts)) }
163
198
  @root = [name, proc]
164
199
  end
165
200
 
@@ -186,7 +221,7 @@ module RASN1
186
221
  # @param [Hash] args
187
222
  def initialize(args={})
188
223
  root = generate_root
189
- set_elements *root
224
+ set_elements(*root)
190
225
  initialize_elements self, args
191
226
  end
192
227
 
@@ -209,7 +244,7 @@ module RASN1
209
244
  # Get name frm root type
210
245
  # @return [String,Symbol]
211
246
  def name
212
- @elements[@root].name
247
+ @root
213
248
  end
214
249
 
215
250
  # Get elements names
@@ -221,7 +256,7 @@ module RASN1
221
256
  # Return a hash image of model
222
257
  # @return [Hash]
223
258
  def to_h
224
- { @root => private_to_h(@elements[@root]) }
259
+ private_to_h
225
260
  end
226
261
 
227
262
  # @return [String]
@@ -328,27 +363,32 @@ module RASN1
328
363
  end
329
364
  end
330
365
 
331
- def private_to_h(element)
332
- if element.is_a?(Types::SequenceOf) or
333
- (element.is_a?(Model) and element.root.is_a?(Types::SequenceOf))
334
- element.value.map { |el| private_to_h(el) }
335
- elsif element.value.is_a? Array
336
- h = {}
337
- element.value.each do |subel|
338
- case subel
339
- when Types::Sequence, Types::Set
340
- h[subel.name] = private_to_h(subel)
341
- when Model
342
- this_name = @elements.key(subel) || element.name
343
- h[this_name] = subel.to_h[subel.name]
344
- else
345
- next if subel.value.nil? and subel.optional?
346
- h[subel.name] = subel.value
347
- end
348
- end
349
- h
366
+ def private_to_h(element=nil)
367
+ my_element = element
368
+ my_element = root if my_element.nil?
369
+ my_element = my_element.root if my_element.is_a?(Model)
370
+ value = case my_element
371
+ when Types::SequenceOf
372
+ if my_element.of_type < Model
373
+ my_element.value.map { |el| el.to_h.values.first }
374
+ else
375
+ my_element.value.map { |el| private_to_h(el) }
376
+ end
377
+ when Types::Sequence
378
+ seq = my_element.value.map do |el|
379
+ next if el.optional? and el.value.nil?
380
+ name = el.is_a?(Model) ? @elements.key(el) : el.name
381
+ [name, private_to_h(el)]
382
+ end
383
+ seq.compact!
384
+ Hash[seq]
385
+ else
386
+ my_element.value
387
+ end
388
+ if element.nil?
389
+ { @root => value }
350
390
  else
351
- element.value
391
+ value
352
392
  end
353
393
  end
354
394
  end
data/lib/rasn1/types.rb CHANGED
@@ -6,15 +6,42 @@ module RASN1
6
6
  # Give all primitive types
7
7
  # @return [Array<Types::Primitive>]
8
8
  def self.primitives
9
- self.constants.map { |c| Types.const_get(c) }.
10
- select { |klass| klass < Primitive }
9
+ @primitives ||= self.constants.map { |c| Types.const_get(c) }.
10
+ select { |klass| klass < Primitive }
11
11
  end
12
12
 
13
13
  # Give all constructed types
14
14
  # @return [Array<Types::Constructed>]
15
15
  def self.constructed
16
- self.constants.map { |c| Types.const_get(c) }.
17
- select { |klass| klass < Constructed }
16
+ @constructed ||= self.constants.map { |c| Types.const_get(c) }.
17
+ select { |klass| klass < Constructed }
18
+ end
19
+
20
+ # Give ASN.1 type from an integer. If +tag+ is unknown, return a {Types::Base}
21
+ # object.
22
+ # @param [Integer] tag
23
+ # @return [Types::Base]
24
+ # @raise [ASN1Error] +tag+ is out of range
25
+ def self.tag2type(tag)
26
+ raise ASN1Error, "tag is out of range" if tag > 0xff
27
+
28
+ if !defined? @tag2types
29
+ constructed = self.constructed - [Types::SequenceOf, Types::SetOf]
30
+ primitives = self.primitives - [Types::Enumerated]
31
+ ary = [primitives, constructed].flatten.map do |type|
32
+ next unless type.const_defined? :TAG
33
+ [type::TAG, type]
34
+ end
35
+ @tag2types = Hash[ary]
36
+ @tag2types.default = Types::Base
37
+ end
38
+
39
+ klass = @tag2types[tag & 0xdf] # Remove CONSTRUCTED bit
40
+ is_constructed = (tag & 0x20) == 0x20
41
+ asn1class = Types::Base::CLASSES.key(tag & 0xc0)
42
+ options = { class: asn1class, constructed: is_constructed }
43
+ options[:tag_value] = (tag & 0x1f) if klass == Types::Base
44
+ klass.new(options)
18
45
  end
19
46
  end
20
47
  end
@@ -13,7 +13,7 @@ module RASN1
13
13
  when Base, Model
14
14
  @value.to_der
15
15
  when nil
16
- Null.new(@name).to_der
16
+ Null.new.to_der
17
17
  else
18
18
  @value.to_s
19
19
  end
@@ -33,14 +33,15 @@ module RASN1
33
33
  def inspect(level=0)
34
34
  str = ''
35
35
  str << ' ' * level if level > 0
36
+ str << "#{@name} " unless @name.nil?
36
37
  if @value.nil?
37
- str << "#{name} (ANY) NULL"
38
+ str << "(ANY) NULL"
38
39
  elsif @value.is_a?(OctetString)
39
- str << "#{name} (ANY) #{@value.type}: #{value.value.inspect}"
40
+ str << "(ANY) #{@value.type}: #{value.value.inspect}"
40
41
  elsif @value.class < Base
41
- str << "#{name} (ANY) #{@value.type}: #{value.value}"
42
+ str << "(ANY) #{@value.type}: #{value.value}"
42
43
  else
43
- str << "#{name} (ANY) #{value.to_s.inspect}"
44
+ str << "(ANY) #{value.to_s.inspect}"
44
45
  end
45
46
  end
46
47
  end
@@ -33,15 +33,15 @@ module RASN1
33
33
  # -- private tag
34
34
  # PType ::= [PRIVATE 2] EXPLICIT INTEGER
35
35
  # These types may be defined as:
36
- # ctype = RASN1::Types::Integer.new(:ctype, explicit: 0) # with explicit, default #asn1_class is :context
37
- # atype = RASN1::Types::Integer.new(:atype, explicit: 1, class: :application)
38
- # ptype = RASN1::Types::Integer.new(:ptype, explicit: 2, class: :private)
36
+ # ctype = RASN1::Types::Integer.new(explicit: 0) # with explicit, default #asn1_class is :context
37
+ # atype = RASN1::Types::Integer.new(explicit: 1, class: :application)
38
+ # ptype = RASN1::Types::Integer.new(explicit: 2, class: :private)
39
39
  # Sometimes, an EXPLICIT type should be CONSTRUCTED. To do that, use +:constructed+
40
40
  # option:
41
- # ptype = RASN1::Types::Integer.new(:ptype, explicit: 2, class: :private, constructed: true)
41
+ # ptype = RASN1::Types::Integer.new(explicit: 2, class: :private, constructed: true)
42
42
  #
43
43
  # Implicit tagged values may also be defined:
44
- # ctype_implicit = RASN1::Types::Integer.new(:ctype, implicit: 0)
44
+ # ctype_implicit = RASN1::Types::Integer.new(implicit: 0)
45
45
  # @author Sylvain Daubert
46
46
  class Base
47
47
  # Allowed ASN.1 tag classes
@@ -58,8 +58,8 @@ module RASN1
58
58
  # Length value for indefinite length
59
59
  INDEFINITE_LENGTH = 0x80
60
60
 
61
- # @return [Symbol, String]
62
- attr_accessor :name
61
+ # @return [String,nil]
62
+ attr_reader :name
63
63
  # @return [Symbol]
64
64
  attr_reader :asn1_class
65
65
  # @return [Object,nil] default value, if defined
@@ -75,23 +75,40 @@ module RASN1
75
75
  end
76
76
 
77
77
 
78
- # @param [Symbol, String] name name for this tag in grammar
79
- # @param [Hash] options
80
- # @option options [Symbol] :class ASN.1 tag class. Default value is +:universal+.
81
- # If +:explicit+ or +:implicit:+ is defined, default value is +:context+.
82
- # @option options [::Boolean] :optional define this tag as optional. Default
83
- # is +false+
84
- # @option options [Object] :default default value for DEFAULT tag
85
- # @option options [Object] :value value to set
86
- # @option options [::Integer] :implicit define an IMPLICIT tagged type
87
- # @option options [::Integer] :explicit define an EXPLICIT tagged type
88
- # @option options [::Boolean] :constructed if +true+, set type as constructed.
89
- # May only be used when +:explicit+ is defined, else it is discarded.
90
- def initialize(name, options={})
91
- @name = name
78
+ # @overload initialize(options={})
79
+ # @param [Hash] options
80
+ # @option options [Symbol] :class ASN.1 tag class. Default value is +:universal+.
81
+ # If +:explicit+ or +:implicit:+ is defined, default value is +:context+.
82
+ # @option options [::Boolean] :optional define this tag as optional. Default
83
+ # is +false+
84
+ # @option options [Object] :default default value for DEFAULT tag
85
+ # @option options [Object] :value value to set
86
+ # @option options [::Integer] :implicit define an IMPLICIT tagged type
87
+ # @option options [::Integer] :explicit define an EXPLICIT tagged type
88
+ # @option options [::Boolean] :constructed if +true+, set type as constructed.
89
+ # May only be used when +:explicit+ is defined, else it is discarded.
90
+ # @option options [::String] :name name for this node
91
+ # @overload initialize(value, options={})
92
+ # @param [Object] value value to set for this ASN.1 object
93
+ # @param [Hash] options
94
+ # @option options [Symbol] :class ASN.1 tag class. Default value is +:universal+.
95
+ # If +:explicit+ or +:implicit:+ is defined, default value is +:context+.
96
+ # @option options [::Boolean] :optional define this tag as optional. Default
97
+ # is +false+
98
+ # @option options [Object] :default default value for DEFAULT tag
99
+ # @option options [::Integer] :implicit define an IMPLICIT tagged type
100
+ # @option options [::Integer] :explicit define an EXPLICIT tagged type
101
+ # @option options [::Boolean] :constructed if +true+, set type as constructed.
102
+ # May only be used when +:explicit+ is defined, else it is discarded.
103
+ # @option options [::String] :name name for this node
104
+ def initialize(value_or_options={}, options={})
92
105
  @constructed = nil
93
-
94
- set_options options
106
+ if value_or_options.is_a? Hash
107
+ set_options value_or_options
108
+ else
109
+ set_options options
110
+ @value = value_or_options
111
+ end
95
112
  end
96
113
 
97
114
  # Used by +#dup+ and +#clone+. Deep copy @value.
@@ -142,11 +159,7 @@ module RASN1
142
159
  # SHOULD respond to +#value_to_der+.
143
160
  # @return [String] DER-formated string
144
161
  def to_der
145
- if self.class.const_defined?('TAG')
146
- build_tag
147
- else
148
- raise NotImplementedError, 'should be implemented by subclasses'
149
- end
162
+ build_tag
150
163
  end
151
164
 
152
165
  # @return [::Boolean] +true+ if this is a primitive type
@@ -168,10 +181,12 @@ module RASN1
168
181
  # Get tag value
169
182
  # @return [Integer]
170
183
  def tag
171
- pc = if @constructed.nil?
184
+ pc = if @constructed.nil?
172
185
  self.class::ASN1_PC
173
- else
186
+ elsif @constructed # true
174
187
  Constructed::ASN1_PC
188
+ else # false
189
+ 0
175
190
  end
176
191
  (@tag_value || self.class::TAG) | CLASSES[@asn1_class] | pc
177
192
  end
@@ -208,7 +223,17 @@ module RASN1
208
223
  def inspect(level=0)
209
224
  str = ''
210
225
  str << ' ' * level if level > 0
211
- str << "#{name} #{type}: #{value}"
226
+ str << "#{@name} " unless @name.nil?
227
+ if self.class == Base
228
+ str << "#{type} (0x#{'%02x' % tag}): "
229
+ if @value.is_a?(Base)
230
+ str << value.inspect(level+1)
231
+ else
232
+ str << value.inspect
233
+ end
234
+ else
235
+ str << "#{type}: #{value.inspect}"
236
+ end
212
237
  end
213
238
 
214
239
  # Objects are equal if they have same class AND same DER
@@ -220,12 +245,26 @@ module RASN1
220
245
 
221
246
  private
222
247
 
248
+ def value_to_der
249
+ case @value
250
+ when Base
251
+ @value.to_der
252
+ else
253
+ @value.to_s
254
+ end
255
+ end
256
+
257
+ def der_to_value(der, ber:false)
258
+ @value = der
259
+ end
260
+
223
261
  def set_options(options)
224
262
  set_class options[:class]
225
263
  set_optional options[:optional]
226
264
  set_default options[:default]
227
265
  set_tag options
228
266
  @value = options[:value]
267
+ @name = options[:name]
229
268
  end
230
269
 
231
270
  def set_class(asn1_class)
@@ -251,6 +290,8 @@ module RASN1
251
290
  @default = default
252
291
  end
253
292
 
293
+ # handle undocumented option +:tag_value+, used internally by
294
+ # {RASN1.parse} to parse non-universal class tags.
254
295
  def set_tag(options)
255
296
  if options[:explicit]
256
297
  @tag = :explicit
@@ -259,6 +300,10 @@ module RASN1
259
300
  elsif options[:implicit]
260
301
  @tag = :implicit
261
302
  @tag_value = options[:implicit]
303
+ @constructed = options[:constructed]
304
+ elsif options[:tag_value]
305
+ @tag_value = options[:tag_value]
306
+ @constructed = options[:constructed]
262
307
  end
263
308
 
264
309
  @asn1_class = :context if @tag and @asn1_class == :universal
@@ -330,14 +375,14 @@ module RASN1
330
375
 
331
376
  if length == INDEFINITE_LENGTH
332
377
  if primitive?
333
- raise ASN1Error, "malformed #{type} TAG (#@name): indefinite length " \
378
+ raise ASN1Error, "malformed #{type} TAG: indefinite length " \
334
379
  "forbidden for primitive types"
335
380
  else
336
381
  if ber
337
- raise NotImplementedError, "TAG #@name: indefinite length not " \
382
+ raise NotImplementedError, "TAG: indefinite length not " \
338
383
  "supported yet"
339
384
  else
340
- raise ASN1Error, "TAG #@name: indefinite length forbidden in DER " \
385
+ raise ASN1Error, "TAG: indefinite length forbidden in DER " \
341
386
  "encoding"
342
387
  end
343
388
  end
@@ -357,12 +402,11 @@ module RASN1
357
402
  end
358
403
 
359
404
  def explicit_type
360
- self.class.new(@name)
405
+ self.class.new
361
406
  end
362
407
 
363
408
  def raise_tag_error(expected_tag, tag)
364
409
  msg = "Expected #{tag2name(expected_tag)} but get #{tag2name(tag)}"
365
- msg << " for #@name"
366
410
  raise ASN1Error, msg
367
411
  end
368
412
 
@@ -9,28 +9,32 @@ module RASN1
9
9
  # @return [Integer] bit length of bit string
10
10
  attr_accessor :bit_length
11
11
 
12
- # @param [Symbol, String] name name for this tag in grammar
13
- # @param [Hash] options
14
- # @option options [Symbol] :class ASN.1 tag class. Default value is +:universal+
15
- # @option options [::Boolean] :optional define this tag as optional. Default
16
- # is +false+
17
- # @option options [Object] :default default value for DEFAULT tag
18
- # @option options [Object] :bit_length default bit_length value. Should be
19
- # present if +:default+ is set
20
- def initialize(name, options={})
12
+ # @overload initialize(options={})
13
+ # @param [Hash] options
14
+ # @option options [Object] :bit_length default bit_length value. Should be
15
+ # present if +:default+ is set
16
+ # @overload initialize(value, options={})
17
+ # @param [Object] value value to set for this ASN.1 object
18
+ # @param [Hash] options
19
+ # @option options [Object] :bit_length default bit_length value. Should be
20
+ # present if +:default+ is set
21
+ # @see Base#initialize common options to all ASN.1 types
22
+ def initialize(value_or_options={}, options={})
21
23
  super
24
+ opts = value_or_options.is_a?(Hash) ? value_or_options : options
22
25
  if @default
23
- if options[:bit_length].nil?
26
+ if opts[:bit_length].nil?
24
27
  raise ASN1Error, "TAG #@name: default bit length is not defined"
25
28
  end
26
- @default_bit_length = options[:bit_length]
29
+ @default_bit_length = opts[:bit_length]
27
30
  end
28
31
  end
29
32
 
30
33
  def inspect(level=0)
31
34
  str = ''
32
35
  str << ' ' * level if level > 0
33
- str << "#{name} #{type}: #{value.inspect} (bit length: #{bit_length})"
36
+ str << "#{name} " unless @name.nil?
37
+ str << "#{type}: #{value.inspect} (bit length: #{bit_length})"
34
38
  end
35
39
 
36
40
  private
@@ -14,6 +14,7 @@ module RASN1
14
14
  when Array
15
15
  str = ''
16
16
  str << ' ' * level if level > 0
17
+ str << "#{@name} " unless @name.nil?
17
18
  level = level.abs
18
19
  str << "#{type}:\n"
19
20
  level += 1
@@ -21,7 +22,9 @@ module RASN1
21
22
  case item
22
23
  when Base, Model
23
24
  next if item.optional? and item.value.nil?
24
- str << ' ' * level + "#{item.inspect(level)}\n"
25
+ str << ' ' * level
26
+ str << "#{item.name} " unless item.name.nil?
27
+ str << "#{item.inspect(level)}\n"
25
28
  else
26
29
  str << item.inspect
27
30
  end
@@ -21,20 +21,24 @@ module RASN1
21
21
  # @return [Hash]
22
22
  attr_reader :enum
23
23
 
24
- # @param [Symbol, String] name name for this tag in grammar
25
- # @param [Hash] options
26
- # @option options [Symbol] :class ASN.1 tag class. Default value is +:universal+
27
- # @option options [::Boolean] :optional define this tag as optional. Default
28
- # is +false+
29
- # @option options [Object] :default default value for DEFAULT tag
30
- # @option options [Hash] :enum enumeration hash. Keys are names, and values
31
- # are integers. This key is mandatory.
32
- # @raise [EnumeratedError] +:enum+ key is not present
33
- # @raise [EnumeratedError] +:default+ value is unknown
34
- def initialize(name, options={})
24
+ # @overload initialize(options={})
25
+ # @option options [Hash] :enum enumeration hash. Keys are names, and values
26
+ # are integers. This key is mandatory.
27
+ # @raise [EnumeratedError] +:enum+ key is not present
28
+ # @raise [EnumeratedError] +:default+ value is unknown
29
+ # @overload initialize(value, options={})
30
+ # @param [Object] value value to set for this ASN.1 object
31
+ # @option options [Hash] :enum enumeration hash. Keys are names, and values
32
+ # are integers. This key is mandatory.
33
+ # @raise [EnumeratedError] +:enum+ key is not present
34
+ # @raise [EnumeratedError] +:default+ value is unknown
35
+ # @see Base#initialize common options to all ASN.1 types
36
+ def initialize(value_or_options={}, options={})
35
37
  super
36
- raise EnumeratedError, 'no enumeration given' unless options.has_key? :enum
37
- @enum = options[:enum]
38
+ opts = value_or_options.is_a?(Hash) ? value_or_options : options
39
+
40
+ raise EnumeratedError, 'no enumeration given' unless opts.has_key? :enum
41
+ @enum = opts[:enum]
38
42
 
39
43
  case @default
40
44
  when String,Symbol
@@ -16,22 +16,8 @@ module RASN1
16
16
  def inspect(level=0)
17
17
  str = ''
18
18
  str << ' ' * level if level > 0
19
- str << "#{name} #{type}: #{value.inspect}"
20
- end
21
-
22
- private
23
-
24
- def value_to_der
25
- case @value
26
- when Base
27
- @value.to_der
28
- else
29
- @value.to_s
30
- end
31
- end
32
-
33
- def der_to_value(der, ber:false)
34
- @value = der
19
+ str << "#{@name} " unless @name.nil?
20
+ str << "#{type}: #{value.inspect}"
35
21
  end
36
22
  end
37
23
  end
@@ -14,9 +14,9 @@ module RASN1
14
14
  # do:
15
15
  # seq = RASN1::Types::Sequence.new(:record)
16
16
  # seq.value = [
17
- # RASN1::Types::Integer(:id),
18
- # RASN1::Types::Integer(:id, explicit: 0, optional: true),
19
- # RASN1::Types::Integer(:id, implicit: 1, default: 0)
17
+ # RASN1::Types::Integer.new(:id),
18
+ # RASN1::Types::Integer.new(:room, explicit: 0, optional: true),
19
+ # RASN1::Types::Integer.new(:house, implicit: 1, default: 0)
20
20
  # ]
21
21
  #
22
22
  # A sequence may also be used without value to not parse sequence content:
@@ -27,20 +27,10 @@ module RASN1
27
27
  class Sequence < Constructed
28
28
  TAG = 0x10
29
29
 
30
- # @param [Symbol, String] name name for this tag in grammar
31
- # @param [Hash] options
32
- # @option options [Symbol] :class ASN.1 tag class. Default value is +:universal+.
33
- # If +:explicit+ or +:implicit:+ is defined, default value is +:context+.
34
- # @option options [::Boolean] :optional define this tag as optional. Default
35
- # is +false+
36
- # @option options [Object] :default default value for DEFAULT tag
37
- # @option options [Object] :value value to set (default is +[]+)
38
- # @option options [::Integer] :implicit define an IMPLICIT tagged type
39
- # @option options [::Integer] :explicit define an EXPLICIT tagged type
40
- # @option options [::Boolean] :constructed if +true+, set type as constructed.
41
- # May only be used when +:explicit+ is defined, else it is discarded.
42
- def initialize(name, options={})
43
- super(name, { value: [] }.merge(options))
30
+ # @see Base#initialize
31
+ def initialize(value_or_options={}, options={})
32
+ super
33
+ @value ||= []
44
34
  end
45
35
 
46
36
  def initialize_copy(other)
@@ -53,8 +53,8 @@ module RASN1
53
53
  # @param [Symbol, String] name name for this tag in grammar
54
54
  # @param [Class, Base] of_type base type for sequence of
55
55
  # @see Base#initialize
56
- def initialize(name, of_type, options={})
57
- super(name, options)
56
+ def initialize(of_type, options={})
57
+ super(options)
58
58
  @of_type = of_type
59
59
  @value = []
60
60
  end
@@ -70,10 +70,10 @@ module RASN1
70
70
  def <<(obj)
71
71
  if of_type_class < Primitive
72
72
  raise ASN1Error, 'object to add should be an Array' unless obj.is_a?(Array)
73
- @value += obj.map { |item| @of_type.new(nil, value: item) }
73
+ @value += obj.map { |item| @of_type.new(item) }
74
74
  elsif composed_of_type?
75
75
  raise ASN1Error, 'object to add should be an Array' unless obj.is_a?(Array)
76
- new_value = of_type_class.new(@of_type.name, value: [])
76
+ new_value = of_type_class.new
77
77
  @of_type.value.each_with_index do |type, i|
78
78
  type2 = type.dup
79
79
  type2.value = obj[i]
@@ -161,7 +161,7 @@ module RASN1
161
161
  end
162
162
 
163
163
  def explicit_type
164
- self.class.new(@name, self.of_type)
164
+ self.class.new(self.of_type)
165
165
  end
166
166
  end
167
167
  end
@@ -5,6 +5,6 @@ module RASN1
5
5
  # @author Sylvain Daubert
6
6
  class VisibleString < IA5String
7
7
  TAG = 26
8
- end
8
+ end
9
9
  end
10
10
  end
data/lib/rasn1/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RASN1
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rasn1
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Daubert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-13 00:00:00.000000000 Z
11
+ date: 2017-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yard