rasn1 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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