rasn1 0.6.8 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/rasn1.svg)](https://badge.fury.io/rb/rasn1)
|
2
|
-
[![Build Status](https://travis-ci.org/sdaubert/rasn1.svg?branch=master)](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
|