rasn1 0.6.8 → 0.9.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 +4 -4
- data/README.md +11 -3
- data/lib/rasn1/model.rb +185 -98
- data/lib/rasn1/types/any.rb +37 -22
- data/lib/rasn1/types/base.rb +217 -171
- data/lib/rasn1/types/bit_string.rb +44 -46
- data/lib/rasn1/types/boolean.rb +22 -14
- data/lib/rasn1/types/choice.rb +11 -16
- data/lib/rasn1/types/constructed.rb +7 -9
- data/lib/rasn1/types/enumerated.rb +10 -15
- data/lib/rasn1/types/generalized_time.rb +105 -64
- data/lib/rasn1/types/ia5string.rb +8 -6
- data/lib/rasn1/types/integer.rb +89 -81
- data/lib/rasn1/types/null.rb +11 -10
- data/lib/rasn1/types/numeric_string.rb +7 -7
- data/lib/rasn1/types/object_id.rb +19 -49
- data/lib/rasn1/types/octet_string.rb +6 -6
- data/lib/rasn1/types/primitive.rb +2 -1
- data/lib/rasn1/types/printable_string.rb +8 -7
- data/lib/rasn1/types/sequence.rb +39 -8
- data/lib/rasn1/types/sequence_of.rb +55 -41
- data/lib/rasn1/types/set.rb +4 -2
- data/lib/rasn1/types/set_of.rb +4 -3
- data/lib/rasn1/types/utc_time.rb +7 -5
- data/lib/rasn1/types/utf8_string.rb +7 -5
- data/lib/rasn1/types/visible_string.rb +4 -3
- data/lib/rasn1/types.rb +54 -24
- data/lib/rasn1/version.rb +3 -1
- data/lib/rasn1.rb +8 -7
- metadata +27 -51
- data/.gitignore +0 -11
- data/.rubocop.yml +0 -28
- data/.travis.yml +0 -9
- data/Gemfile +0 -4
- data/Rakefile +0 -12
- data/rasn1.gemspec +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0f5f3f69aaae20cfd16576f565bc52d198bea49921a0db15e3e2a95a4947853
|
4
|
+
data.tar.gz: c3c1f6b2d5019febcbff3812611d624094b7aaefc238bd70109d4c278be3af8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51e54a40d6608074e76ba0d18d51462e82fba109a4258b9082875bafe36476060186d2081cabb4e2d17e1140f53a4700906a053fdb05638ceb060560a337d05b
|
7
|
+
data.tar.gz: 434ca0398606fb411351a2d43b6701b70f9512043abea8768e21832a2a1800be8347efef50b17b01239ce953b49cb21b64860e2d252cc64e9c696a514de564ea
|
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
[](https://badge.fury.io/rb/rasn1)
|
2
|
-
[](https://travis-ci.org/sdaubert/rasn1)
|
3
2
|
|
4
3
|
# Rasn1
|
5
4
|
|
@@ -15,13 +14,22 @@ gem 'rasn1'
|
|
15
14
|
|
16
15
|
And then execute:
|
17
16
|
|
18
|
-
$ bundle
|
17
|
+
$ bundle install
|
19
18
|
|
20
19
|
Or install it yourself as:
|
21
20
|
|
22
21
|
$ gem install rasn1
|
23
22
|
|
24
|
-
##
|
23
|
+
## Simple usage
|
24
|
+
|
25
|
+
To decode a DER/BER string without checking a model, do:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
decoded_der = RASN1.parse(der_string)
|
29
|
+
decoded_ber = RASN1.parse(ber_string, ber: true)
|
30
|
+
```
|
31
|
+
|
32
|
+
## Advanced usage
|
25
33
|
All examples below will be based on:
|
26
34
|
|
27
35
|
```
|
data/lib/rasn1/model.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module RASN1
|
3
4
|
# @abstract
|
4
5
|
# {Model} class is a base class to define ASN.1 models.
|
5
6
|
# == Create a simple ASN.1 model
|
@@ -57,7 +58,9 @@ module RASN1
|
|
57
58
|
# All methods defined by root may be delegated by model, unless model also defines
|
58
59
|
# this method.
|
59
60
|
# @author Sylvain Daubert
|
60
|
-
class Model
|
61
|
+
class Model # rubocop:disable Metrics/ClassLength
|
62
|
+
# @private
|
63
|
+
Elem = Struct.new(:name, :proc_or_class, :content)
|
61
64
|
|
62
65
|
class << self
|
63
66
|
# @return [Hash]
|
@@ -66,8 +69,9 @@ module RASN1
|
|
66
69
|
# Use another model in this model
|
67
70
|
# @param [String,Symbol] name
|
68
71
|
# @param [Class] model_klass
|
72
|
+
# @return [Elem]
|
69
73
|
def model(name, model_klass)
|
70
|
-
@root =
|
74
|
+
@root = Elem.new(name, model_klass, nil)
|
71
75
|
end
|
72
76
|
|
73
77
|
# Update options of root element.
|
@@ -92,135 +96,153 @@ module RASN1
|
|
92
96
|
# @return [void]
|
93
97
|
def inherited(klass)
|
94
98
|
super
|
95
|
-
root =
|
99
|
+
root = @root
|
96
100
|
klass.class_eval { @root = root }
|
97
101
|
end
|
98
102
|
|
99
103
|
# @method sequence(name, options)
|
100
104
|
# @param [Symbol,String] name name of object in model
|
101
105
|
# @param [Hash] options
|
106
|
+
# @return [Elem]
|
102
107
|
# @see Types::Sequence#initialize
|
103
108
|
# @method set(name, options)
|
104
109
|
# @param [Symbol,String] name name of object in model
|
105
110
|
# @param [Hash] options
|
111
|
+
# @return [Elem]
|
106
112
|
# @see Types::Set#initialize
|
107
113
|
# @method choice(name, options)
|
108
114
|
# @param [Symbol,String] name name of object in model
|
109
115
|
# @param [Hash] options
|
116
|
+
# @return [Elem]
|
110
117
|
# @see Types::Choice#initialize
|
111
|
-
%w
|
118
|
+
%w[sequence set choice].each do |type|
|
112
119
|
class_eval "def #{type}(name, options={})\n" \
|
113
120
|
" options.merge!(name: name)\n" \
|
114
|
-
" proc =
|
121
|
+
" proc = proc do |opts|\n" \
|
115
122
|
" Types::#{type.capitalize}.new(options.merge(opts))\n" \
|
116
123
|
" end\n" \
|
117
|
-
" @root =
|
118
|
-
|
119
|
-
" @root\n" \
|
120
|
-
"end"
|
124
|
+
" @root = Elem.new(name, proc, options[:content])\n" \
|
125
|
+
'end'
|
121
126
|
end
|
122
127
|
|
123
128
|
# @method sequence_of(name, type, options)
|
124
129
|
# @param [Symbol,String] name name of object in model
|
125
130
|
# @param [Model, Types::Base] type type for SEQUENCE OF
|
126
131
|
# @param [Hash] options
|
132
|
+
# @return [Elem]
|
127
133
|
# @see Types::SequenceOf#initialize
|
128
134
|
# @method set_of(name, type, options)
|
129
135
|
# @param [Symbol,String] name name of object in model
|
130
136
|
# @param [Model, Types::Base] type type for SET OF
|
131
137
|
# @param [Hash] options
|
138
|
+
# @return [Elem]
|
132
139
|
# @see Types::SetOf#initialize
|
133
|
-
%w
|
140
|
+
%w[sequence set].each do |type|
|
134
141
|
klass_name = "Types::#{type.capitalize}Of"
|
135
142
|
class_eval "def #{type}_of(name, type, options={})\n" \
|
136
143
|
" options.merge!(name: name)\n" \
|
137
|
-
" proc =
|
144
|
+
" proc = proc do |opts|\n" \
|
138
145
|
" #{klass_name}.new(type, options.merge(opts))\n" \
|
139
146
|
" end\n" \
|
140
|
-
" @root =
|
141
|
-
|
147
|
+
" @root = Elem.new(name, proc, nil)\n" \
|
148
|
+
'end'
|
142
149
|
end
|
143
150
|
|
144
151
|
# @method boolean(name, options)
|
145
152
|
# @param [Symbol,String] name name of object in model
|
146
153
|
# @param [Hash] options
|
154
|
+
# @return [Elem]
|
147
155
|
# @see Types::Boolean#initialize
|
148
156
|
# @method integer(name, options)
|
149
157
|
# @param [Symbol,String] name name of object in model
|
150
158
|
# @param [Hash] options
|
159
|
+
# @return [Elem]
|
151
160
|
# @see Types::Integer#initialize
|
152
161
|
# @method bit_string(name, options)
|
153
162
|
# @param [Symbol,String] name name of object in model
|
154
163
|
# @param [Hash] options
|
164
|
+
# @return [Elem]
|
155
165
|
# @see Types::BitString#initialize
|
156
166
|
# @method octet_string(name, options)
|
157
167
|
# @param [Symbol,String] name name of object in model
|
158
168
|
# @param [Hash] options
|
169
|
+
# @return [Elem]
|
159
170
|
# @see Types::OctetString#initialize
|
160
171
|
# @method null(name, options)
|
161
172
|
# @param [Symbol,String] name name of object in model
|
162
173
|
# @param [Hash] options
|
174
|
+
# @return [Elem]
|
163
175
|
# @see Types::Null#initialize
|
164
176
|
# @method enumerated(name, options)
|
165
177
|
# @param [Symbol,String] name name of object in model
|
166
178
|
# @param [Hash] options
|
179
|
+
# @return [Elem]
|
167
180
|
# @see Types::Enumerated#initialize
|
168
181
|
# @method utf8_string(name, options)
|
169
182
|
# @param [Symbol,String] name name of object in model
|
170
183
|
# @param [Hash] options
|
184
|
+
# @return [Elem]
|
171
185
|
# @see Types::Utf8String#initialize
|
172
186
|
# @method numeric_string(name, options)
|
173
187
|
# @param [Symbol,String] name name of object in model
|
174
188
|
# @param [Hash] options
|
189
|
+
# @return [Elem]
|
175
190
|
# @see Types::NumericString#initialize
|
176
191
|
# @method printable_string(name, options)
|
177
192
|
# @param [Symbol,String] name name of object in model
|
178
193
|
# @param [Hash] options
|
194
|
+
# @return [Elem]
|
179
195
|
# @see Types::PrintableString#initialize
|
180
196
|
# @method visible_string(name, options)
|
181
197
|
# @param [Symbol,String] name name of object in model
|
182
198
|
# @param [Hash] options
|
199
|
+
# @return [Elem]
|
183
200
|
# @see Types::VisibleString#initialize
|
184
201
|
# @method ia5_string(name, options)
|
185
202
|
# @param [Symbol,String] name name of object in model
|
186
203
|
# @param [Hash] options
|
204
|
+
# @return [Elem]
|
187
205
|
# @see Types::IA5String#initialize
|
188
206
|
Types.primitives.each do |prim|
|
189
207
|
next if prim == Types::ObjectId
|
208
|
+
|
190
209
|
method_name = prim.type.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase.gsub(/\s+/, '_')
|
191
210
|
class_eval "def #{method_name}(name, options={})\n" \
|
192
211
|
" options.merge!(name: name)\n" \
|
193
|
-
" proc =
|
194
|
-
" #{prim
|
212
|
+
" proc = proc do |opts|\n" \
|
213
|
+
" #{prim}.new(options.merge(opts))\n" \
|
195
214
|
" end\n" \
|
196
|
-
" @root =
|
197
|
-
|
215
|
+
" @root = Elem.new(name, proc, nil)\n" \
|
216
|
+
'end'
|
198
217
|
end
|
199
218
|
|
200
219
|
# @param [Symbol,String] name name of object in model
|
201
220
|
# @param [Hash] options
|
221
|
+
# @return [Elem]
|
202
222
|
# @note This method is named +objectid+ and not +object_id+ to not override
|
203
223
|
# +Object#object_id+.
|
204
224
|
# @see Types::ObjectId#initialize
|
205
225
|
def objectid(name, options={})
|
206
|
-
options
|
207
|
-
proc =
|
208
|
-
@root =
|
226
|
+
options[:name] = name
|
227
|
+
proc = proc { |opts| Types::ObjectId.new(options.merge(opts)) }
|
228
|
+
@root = Elem.new(name, proc, nil)
|
209
229
|
end
|
210
230
|
|
211
231
|
# @param [Symbol,String] name name of object in model
|
212
232
|
# @param [Hash] options
|
233
|
+
# @return [Elem]
|
213
234
|
# @see Types::Any#initialize
|
214
235
|
def any(name, options={})
|
215
|
-
options
|
216
|
-
proc =
|
217
|
-
@root =
|
236
|
+
options[:name] = name
|
237
|
+
proc = proc { |opts| Types::Any.new(options.merge(opts)) }
|
238
|
+
@root = Elem.new(name, proc, nil)
|
218
239
|
end
|
219
240
|
|
220
241
|
# Give type name (aka class name)
|
221
242
|
# @return [String]
|
222
243
|
def type
|
223
244
|
return @type if defined? @type
|
245
|
+
|
224
246
|
@type = self.to_s.gsub(/.*::/, '')
|
225
247
|
end
|
226
248
|
|
@@ -231,7 +253,7 @@ module RASN1
|
|
231
253
|
# @raise [ASN1Error] error on parsing
|
232
254
|
def parse(str, ber: false)
|
233
255
|
model = new
|
234
|
-
model.parse!
|
256
|
+
model.parse!(str, ber: ber)
|
235
257
|
model
|
236
258
|
end
|
237
259
|
end
|
@@ -240,8 +262,8 @@ module RASN1
|
|
240
262
|
# @param [Hash] args
|
241
263
|
def initialize(args={})
|
242
264
|
root = generate_root
|
243
|
-
set_elements(
|
244
|
-
initialize_elements
|
265
|
+
set_elements(root)
|
266
|
+
initialize_elements(self, args)
|
245
267
|
end
|
246
268
|
|
247
269
|
# Give access to element +name+ in model
|
@@ -256,14 +278,15 @@ module RASN1
|
|
256
278
|
# @param [Object] value
|
257
279
|
# @return [Object] value
|
258
280
|
def []=(name, value)
|
259
|
-
raise Error,
|
281
|
+
raise Error, 'cannot set value for a Model' if @elements[name].is_a? Model
|
282
|
+
|
260
283
|
@elements[name].value = value
|
261
284
|
end
|
262
285
|
|
263
|
-
# Get name
|
286
|
+
# Get name from root type
|
264
287
|
# @return [String,Symbol]
|
265
288
|
def name
|
266
|
-
@
|
289
|
+
@root_name
|
267
290
|
end
|
268
291
|
|
269
292
|
# Get elements names
|
@@ -278,15 +301,15 @@ module RASN1
|
|
278
301
|
private_to_h
|
279
302
|
end
|
280
303
|
|
281
|
-
# @return [String]
|
282
|
-
def to_der
|
283
|
-
@elements[@root].to_der
|
284
|
-
end
|
285
|
-
|
286
304
|
# Get root element from model
|
287
305
|
# @return [Types::Base,Model]
|
288
306
|
def root
|
289
|
-
@elements[@
|
307
|
+
@elements[@root_name]
|
308
|
+
end
|
309
|
+
|
310
|
+
# @return [String]
|
311
|
+
def to_der
|
312
|
+
root.to_der
|
290
313
|
end
|
291
314
|
|
292
315
|
# Give type name (aka class name)
|
@@ -301,19 +324,62 @@ module RASN1
|
|
301
324
|
# @return [Integer] number of parsed bytes
|
302
325
|
# @raise [ASN1Error] error on parsing
|
303
326
|
def parse!(str, ber: false)
|
304
|
-
|
327
|
+
root.parse!(str.dup.force_encoding('BINARY'), ber: ber)
|
328
|
+
end
|
329
|
+
|
330
|
+
# @overload value
|
331
|
+
# Get value of root element
|
332
|
+
# @return [Object,nil]
|
333
|
+
# @overload value(name, *args)
|
334
|
+
# Direct access to the value of +name+ (nested) element of model.
|
335
|
+
# @param [String,Symbol] name
|
336
|
+
# @param [Array<Integer,String,Symbol>] args more argument to access element. May be
|
337
|
+
# used to access content of a SequenceOf or a SetOf
|
338
|
+
# @return [Object,nil]
|
339
|
+
# @return [Object,nil]
|
340
|
+
# @example
|
341
|
+
# class MyModel1 < RASN1::Model
|
342
|
+
# sequence('seq', content: [boolean('boolean'), integer('int')])
|
343
|
+
# end
|
344
|
+
# class MyModel2 < RASN1::Model
|
345
|
+
# sequence('root', content: [sequence_of('list', MyModel1)])
|
346
|
+
# end
|
347
|
+
# model = MyModel2.new
|
348
|
+
# model.parse!(der)
|
349
|
+
# # access to 2nd MyModel1.int in list
|
350
|
+
# model.value('list', 1, 'int')
|
351
|
+
def value(name=nil, *args)
|
352
|
+
if name.nil?
|
353
|
+
root.value
|
354
|
+
else
|
355
|
+
elt = by_name(name)
|
356
|
+
|
357
|
+
unless args.empty?
|
358
|
+
args.each do |arg|
|
359
|
+
elt = elt.root if elt.is_a?(Model)
|
360
|
+
elt = elt[arg]
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
elt.value
|
365
|
+
end
|
305
366
|
end
|
306
367
|
|
307
368
|
# Delegate some methods to root element
|
308
369
|
# @param [Symbol] meth
|
309
370
|
def method_missing(meth, *args)
|
310
|
-
if
|
311
|
-
|
371
|
+
if root.respond_to? meth
|
372
|
+
root.send meth, *args
|
312
373
|
else
|
313
374
|
super
|
314
375
|
end
|
315
376
|
end
|
316
377
|
|
378
|
+
# @return [Boolean]
|
379
|
+
def respond_to_missing?(meth, *)
|
380
|
+
root.respond_to?(meth) || super
|
381
|
+
end
|
382
|
+
|
317
383
|
# @return [String]
|
318
384
|
def inspect(level=0)
|
319
385
|
' ' * level + "(#{type}) #{root.inspect(-level)}"
|
@@ -326,16 +392,34 @@ module RASN1
|
|
326
392
|
(other.class == self.class) && (other.to_der == self.to_der)
|
327
393
|
end
|
328
394
|
|
329
|
-
|
395
|
+
protected
|
396
|
+
|
397
|
+
# Give a (nested) element from its name
|
398
|
+
# @param [String, Symbol] name
|
399
|
+
# @return [Model, Types::Base]
|
400
|
+
def by_name(name)
|
401
|
+
elt = self[name]
|
402
|
+
return elt unless elt.nil?
|
330
403
|
|
331
|
-
|
332
|
-
|
404
|
+
@elements.each_key do |subelt_name|
|
405
|
+
if self[subelt_name].is_a?(Model)
|
406
|
+
elt = self[subelt_name][name]
|
407
|
+
return elt unless elt.nil?
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
nil
|
333
412
|
end
|
334
413
|
|
335
|
-
|
336
|
-
|
414
|
+
private
|
415
|
+
|
416
|
+
def composed?(elt)
|
417
|
+
[Types::Sequence, Types::Set].include? elt.class
|
337
418
|
end
|
338
419
|
|
420
|
+
# proc_or_class:
|
421
|
+
# * proc: a Types::Base subclass
|
422
|
+
# * class: a model
|
339
423
|
def get_type(proc_or_class, options={})
|
340
424
|
case proc_or_class
|
341
425
|
when Proc
|
@@ -346,84 +430,87 @@ module RASN1
|
|
346
430
|
end
|
347
431
|
|
348
432
|
def generate_root
|
349
|
-
|
350
|
-
@
|
433
|
+
class_element = self.class.class_eval { @root }
|
434
|
+
@root_name = class_element.name
|
351
435
|
@elements = {}
|
352
|
-
@elements[@
|
353
|
-
|
436
|
+
@elements[@root_name] = get_type(class_element.proc_or_class, self.class.options || {})
|
437
|
+
class_element
|
354
438
|
end
|
355
439
|
|
356
|
-
def set_elements(
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
subel
|
365
|
-
end
|
440
|
+
def set_elements(element) # rubocop:disable Naming/AccessorMethodName
|
441
|
+
return unless element.content.is_a? Array
|
442
|
+
|
443
|
+
@elements[name].value = element.content.map do |another_element|
|
444
|
+
subel = get_type(another_element.proc_or_class)
|
445
|
+
@elements[another_element.name] = subel
|
446
|
+
set_elements(another_element) if composed?(subel) && another_element.content.is_a?(Array)
|
447
|
+
subel
|
366
448
|
end
|
367
449
|
end
|
368
450
|
|
369
451
|
def initialize_elements(obj, args)
|
370
452
|
args.each do |name, value|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
obj[name]
|
383
|
-
end
|
384
|
-
if composed.of_type.is_a? Model
|
385
|
-
value.each do |el|
|
386
|
-
composed << initialize_elements(composed.of_type.class.new, el)
|
387
|
-
end
|
388
|
-
else
|
389
|
-
value.each do |el|
|
390
|
-
obj[name] << el
|
391
|
-
end
|
392
|
-
end
|
393
|
-
else
|
394
|
-
obj[name].value = value
|
395
|
-
end
|
453
|
+
next unless obj[name]
|
454
|
+
|
455
|
+
case value
|
456
|
+
when Hash
|
457
|
+
raise ArgumentError, "element #{name}: may only pass a Hash for Model elements" unless obj[name].is_a? Model
|
458
|
+
|
459
|
+
initialize_elements obj[name], value
|
460
|
+
when Array
|
461
|
+
initialize_element_from_array(obj[name], value)
|
462
|
+
else
|
463
|
+
obj[name].value = value
|
396
464
|
end
|
397
465
|
end
|
398
466
|
end
|
399
467
|
|
468
|
+
def initialize_element_from_array(obj, value)
|
469
|
+
composed = obj.is_a?(Model) ? obj.root : obj
|
470
|
+
if composed.of_type.is_a?(Model)
|
471
|
+
value.each do |el|
|
472
|
+
composed << initialize_elements(composed.of_type.class.new, el)
|
473
|
+
end
|
474
|
+
else
|
475
|
+
value.each { |el| composed << el }
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
400
479
|
def private_to_h(element=nil)
|
401
|
-
my_element = element
|
402
|
-
my_element = root if my_element.nil?
|
480
|
+
my_element = element || root
|
403
481
|
my_element = my_element.root if my_element.is_a?(Model)
|
404
482
|
value = case my_element
|
405
483
|
when Types::SequenceOf
|
406
|
-
|
407
|
-
my_element.value.map { |el| el.to_h.values.first }
|
408
|
-
else
|
409
|
-
my_element.value.map { |el| private_to_h(el) }
|
410
|
-
end
|
484
|
+
sequence_of_to_h(my_element)
|
411
485
|
when Types::Sequence
|
412
|
-
|
413
|
-
next if el.optional? and el.value.nil?
|
414
|
-
name = el.is_a?(Model) ? @elements.key(el) : el.name
|
415
|
-
[name, private_to_h(el)]
|
416
|
-
end
|
417
|
-
seq.compact!
|
418
|
-
Hash[seq]
|
486
|
+
sequence_to_h(my_element)
|
419
487
|
else
|
420
488
|
my_element.value
|
421
489
|
end
|
422
490
|
if element.nil?
|
423
|
-
{ @
|
491
|
+
{ @root_name => value }
|
424
492
|
else
|
425
493
|
value
|
426
494
|
end
|
427
495
|
end
|
496
|
+
|
497
|
+
def sequence_of_to_h(elt)
|
498
|
+
if elt.of_type < Model
|
499
|
+
elt.value.map { |el| el.to_h.values.first }
|
500
|
+
else
|
501
|
+
elt.value.map { |el| private_to_h(el) }
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
def sequence_to_h(seq)
|
506
|
+
ary = seq.value.map do |el|
|
507
|
+
next if el.optional? && el.value.nil?
|
508
|
+
|
509
|
+
name = el.is_a?(Model) ? @elements.key(el) : el.name
|
510
|
+
[name, private_to_h(el)]
|
511
|
+
end
|
512
|
+
ary.compact!
|
513
|
+
ary.to_h
|
514
|
+
end
|
428
515
|
end
|
429
516
|
end
|
data/lib/rasn1/types/any.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RASN1
|
2
4
|
module Types
|
3
|
-
|
4
5
|
# ASN.1 ANY: accepts any types
|
5
6
|
#
|
6
7
|
# If `any#value` is `nil` and Any object is not {#optional?}, `any` will be encoded as a {Null} object.
|
7
8
|
# @author Sylvain Daubert
|
8
9
|
class Any < Base
|
9
|
-
|
10
10
|
# @return [String] DER-formated string
|
11
11
|
def to_der
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
if value?
|
13
|
+
case @value
|
14
|
+
when Base, Model
|
15
|
+
@value.to_der
|
16
|
+
else
|
17
|
+
@value.to_s
|
18
|
+
end
|
17
19
|
else
|
18
|
-
|
20
|
+
optional? ? '' : Null.new.to_der
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
@@ -25,30 +27,43 @@ module RASN1
|
|
25
27
|
# @param [Boolean] ber if +true+, accept BER encoding
|
26
28
|
# @return [Integer] total number of parsed bytes
|
27
29
|
def parse!(der, ber: false)
|
28
|
-
if der.
|
30
|
+
if der.empty?
|
29
31
|
return 0 if optional?
|
30
32
|
|
31
|
-
raise ASN1Error,
|
33
|
+
raise ASN1Error, 'Expected ANY but get nothing'
|
32
34
|
end
|
33
35
|
|
34
|
-
|
36
|
+
id_size = Types.decode_identifier_octets(der).last
|
37
|
+
total_length, = get_data(der[id_size..-1], ber)
|
38
|
+
total_length += id_size
|
39
|
+
|
40
|
+
@no_value = false
|
35
41
|
@value = der[0, total_length]
|
42
|
+
|
36
43
|
total_length
|
37
44
|
end
|
38
45
|
|
39
46
|
def inspect(level=0)
|
40
|
-
str =
|
41
|
-
str <<
|
47
|
+
str = common_inspect(level)
|
48
|
+
str << if !value?
|
49
|
+
'NULL'
|
50
|
+
elsif @value.is_a?(OctetString) || @value.is_a?(BitString)
|
51
|
+
"#{@value.type}: #{value.value.inspect}"
|
52
|
+
elsif @value.class < Base
|
53
|
+
"#{@value.type}: #{value.value}"
|
54
|
+
else
|
55
|
+
value.to_s.inspect
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def common_inspect(level)
|
60
|
+
lvl = level >= 0 ? level : 0
|
61
|
+
str = ' ' * lvl
|
42
62
|
str << "#{@name} " unless @name.nil?
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
elsif @value.class < Base
|
48
|
-
str << "(ANY) #{@value.type}: #{value.value}"
|
49
|
-
else
|
50
|
-
str << "ANY: #{value.to_s.inspect}"
|
51
|
-
end
|
63
|
+
str << asn1_class.to_s.upcase << ' ' unless asn1_class == :universal
|
64
|
+
str << "[#{id}] EXPLICIT " if explicit?
|
65
|
+
str << "[#{id}] IMPLICIT " if implicit?
|
66
|
+
str << '(ANY) '
|
52
67
|
end
|
53
68
|
end
|
54
69
|
end
|