rasn1 0.16.2 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +25 -10
- data/lib/rasn1/errors.rb +2 -2
- data/lib/rasn1/model/accel.rb +229 -0
- data/lib/rasn1/model.rb +125 -211
- data/lib/rasn1/tracer.rb +34 -14
- data/lib/rasn1/types/any.rb +24 -3
- data/lib/rasn1/types/base.rb +132 -36
- data/lib/rasn1/types/bit_string.rb +18 -5
- data/lib/rasn1/types/boolean.rb +14 -3
- data/lib/rasn1/types/choice.rb +39 -23
- data/lib/rasn1/types/constrained.rb +4 -3
- data/lib/rasn1/types/constructed.rb +4 -2
- data/lib/rasn1/types/enumerated.rb +9 -8
- data/lib/rasn1/types/generalized_time.rb +32 -13
- data/lib/rasn1/types/integer.rb +67 -11
- data/lib/rasn1/types/null.rb +7 -3
- data/lib/rasn1/types/numeric_string.rb +14 -2
- data/lib/rasn1/types/object_id.rb +15 -4
- data/lib/rasn1/types/octet_string.rb +3 -3
- data/lib/rasn1/types/primitive.rb +4 -0
- data/lib/rasn1/types/printable_string.rb +9 -2
- data/lib/rasn1/types/sequence.rb +7 -3
- data/lib/rasn1/types/sequence_of.rb +28 -8
- data/lib/rasn1/types/set_of.rb +1 -1
- data/lib/rasn1/types/utc_time.rb +7 -2
- data/lib/rasn1/types.rb +5 -5
- data/lib/rasn1/version.rb +1 -1
- data/lib/rasn1/wrapper.rb +38 -7
- data/lib/rasn1.rb +8 -7
- metadata +5 -4
data/lib/rasn1/types/base.rb
CHANGED
|
@@ -75,7 +75,7 @@ module RASN1
|
|
|
75
75
|
attr_reader :asn1_class
|
|
76
76
|
# @return [Object,nil] default value, if defined
|
|
77
77
|
attr_reader :default
|
|
78
|
-
# @return [Hash
|
|
78
|
+
# @return [Hash{Symbol => Object}]
|
|
79
79
|
attr_reader :options
|
|
80
80
|
# @return [String] raw parsed data
|
|
81
81
|
attr_reader :raw_data
|
|
@@ -99,10 +99,10 @@ module RASN1
|
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
# Parse a DER or BER string
|
|
102
|
-
# @param [String]
|
|
103
|
-
# @param [Hash]
|
|
104
|
-
# @return [Base]
|
|
102
|
+
# @param der_or_ber [String] string to parse
|
|
103
|
+
# @param options [Hash]
|
|
105
104
|
# @option options [Boolean] :ber if +true+, parse a BER string, else a DER one
|
|
105
|
+
# @return [Base]
|
|
106
106
|
# @note More options are supported. See {Base#initialize}.
|
|
107
107
|
def self.parse(der_or_ber, options={})
|
|
108
108
|
obj = self.new(options)
|
|
@@ -117,18 +117,19 @@ module RASN1
|
|
|
117
117
|
false
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
123
|
-
#
|
|
124
|
-
#
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
#
|
|
128
|
-
#
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
120
|
+
# @!macro [new] type_initialize
|
|
121
|
+
# @param options [Hash]
|
|
122
|
+
# @option options [Symbol] :class ASN.1 class. Default value is +:universal+.
|
|
123
|
+
# If +:explicit+ or +:implicit:+ is defined, default value is +:context+.
|
|
124
|
+
# @option options [::Boolean] :optional define this tag as optional. Default
|
|
125
|
+
# is +false+
|
|
126
|
+
# @option options [Object] :default default value (ASN.1 DEFAULT)
|
|
127
|
+
# @option options [Object] :value value to set
|
|
128
|
+
# @option options [::Integer] :implicit define an IMPLICIT tagged type
|
|
129
|
+
# @option options [::Integer] :explicit define an EXPLICIT tagged type
|
|
130
|
+
# @option options [::Boolean] :constructed if +true+, set type as constructed.
|
|
131
|
+
# May only be used when +:explicit+ is defined, else it is discarded.
|
|
132
|
+
# @option options [::String] :name name for this node
|
|
132
133
|
def initialize(options={})
|
|
133
134
|
@constructed = nil
|
|
134
135
|
set_value(options.delete(:value))
|
|
@@ -142,6 +143,7 @@ module RASN1
|
|
|
142
143
|
def specific_initializer; end
|
|
143
144
|
|
|
144
145
|
# Deep copy @value and @default.
|
|
146
|
+
# @return [void]
|
|
145
147
|
def initialize_copy(*)
|
|
146
148
|
super
|
|
147
149
|
@value = @value.dup
|
|
@@ -150,6 +152,7 @@ module RASN1
|
|
|
150
152
|
end
|
|
151
153
|
|
|
152
154
|
# Get value or default value
|
|
155
|
+
# @return [Object]
|
|
153
156
|
def value
|
|
154
157
|
if value?
|
|
155
158
|
@value
|
|
@@ -159,12 +162,16 @@ module RASN1
|
|
|
159
162
|
end
|
|
160
163
|
|
|
161
164
|
# Set value. If +val+ is +nil+, unset value
|
|
162
|
-
#
|
|
165
|
+
# @!macro [new] value_setter
|
|
166
|
+
# @param val [Object,nil]
|
|
167
|
+
# @return [Object] return +val+
|
|
163
168
|
def value=(val)
|
|
164
169
|
set_value(val)
|
|
165
170
|
end
|
|
166
171
|
|
|
167
172
|
# @abstract Define 'void' value (i.e. 'value' when no value was set)
|
|
173
|
+
# For base type, this is an empty string
|
|
174
|
+
# @return [Object]
|
|
168
175
|
def void_value
|
|
169
176
|
''
|
|
170
177
|
end
|
|
@@ -202,11 +209,13 @@ module RASN1
|
|
|
202
209
|
build
|
|
203
210
|
end
|
|
204
211
|
|
|
212
|
+
# Say if self is defined as primitive (subclass of {Primitive} and constructed not defined in tag)
|
|
205
213
|
# @return [::Boolean] +true+ if this is a primitive type
|
|
206
214
|
def primitive?
|
|
207
215
|
(self.class < Primitive) && !@constructed
|
|
208
216
|
end
|
|
209
217
|
|
|
218
|
+
# Say if self is defined as constructed (subclass of {Constructed} or constructed defined in tag)
|
|
210
219
|
# @return [::Boolean] +true+ if this is a constructed type
|
|
211
220
|
def constructed?
|
|
212
221
|
(self.class < Constructed) || !!@constructed
|
|
@@ -227,8 +236,8 @@ module RASN1
|
|
|
227
236
|
# @abstract This method SHOULD be partly implemented by subclasses to parse
|
|
228
237
|
# data. Subclasses SHOULD respond to +#der_to_value+.
|
|
229
238
|
# Parse a DER string. This method updates object.
|
|
230
|
-
# @param [String]
|
|
231
|
-
# @param [Boolean]
|
|
239
|
+
# @param der [String] DER string
|
|
240
|
+
# @param ber [Boolean] if +true+, accept BER encoding
|
|
232
241
|
# @return [Integer] total number of parsed bytes
|
|
233
242
|
# @raise [ASN1Error] error on parsing
|
|
234
243
|
def parse!(der, ber: false)
|
|
@@ -250,7 +259,7 @@ module RASN1
|
|
|
250
259
|
value_to_der.size
|
|
251
260
|
end
|
|
252
261
|
|
|
253
|
-
# @param [Integer]
|
|
262
|
+
# @param level [Integer]
|
|
254
263
|
# @return [String]
|
|
255
264
|
def inspect(level=0)
|
|
256
265
|
str = common_inspect(level)
|
|
@@ -261,14 +270,14 @@ module RASN1
|
|
|
261
270
|
end
|
|
262
271
|
|
|
263
272
|
# Objects are equal if they have same class AND same DER
|
|
264
|
-
# @param [Base]
|
|
273
|
+
# @param other [Base]
|
|
265
274
|
# @return [Boolean]
|
|
266
275
|
def ==(other)
|
|
267
276
|
(other.class == self.class) && (other.to_der == self.to_der)
|
|
268
277
|
end
|
|
269
278
|
|
|
270
279
|
# Set options to this object
|
|
271
|
-
# @param [Hash]
|
|
280
|
+
# @param options [Hash]
|
|
272
281
|
# @return [void]
|
|
273
282
|
# @since 0.12
|
|
274
283
|
def options=(options)
|
|
@@ -307,10 +316,12 @@ module RASN1
|
|
|
307
316
|
end
|
|
308
317
|
end
|
|
309
318
|
|
|
310
|
-
# @private
|
|
311
|
-
#
|
|
312
|
-
#
|
|
313
|
-
#
|
|
319
|
+
# @private
|
|
320
|
+
# Parse tage and length from binary string. Return data length and binary data.
|
|
321
|
+
# @!macro [new] do_parse
|
|
322
|
+
# @param der [String]
|
|
323
|
+
# @param ber [Boolean]
|
|
324
|
+
# @return [Array(::Integer, String)]
|
|
314
325
|
# @since 0.15.0 was private before
|
|
315
326
|
def do_parse(der, ber: false)
|
|
316
327
|
return [0, ''] unless check_id(der)
|
|
@@ -323,8 +334,9 @@ module RASN1
|
|
|
323
334
|
[total_length, data]
|
|
324
335
|
end
|
|
325
336
|
|
|
326
|
-
# @private
|
|
327
|
-
#
|
|
337
|
+
# @private
|
|
338
|
+
# Delegate to explicit type to generate sub-value
|
|
339
|
+
# @param data [String]
|
|
328
340
|
# @return [void]
|
|
329
341
|
# @since 0.15.0 was private before
|
|
330
342
|
def do_parse_explicit(data)
|
|
@@ -334,8 +346,8 @@ module RASN1
|
|
|
334
346
|
end
|
|
335
347
|
|
|
336
348
|
# Make value from DER/BER string
|
|
337
|
-
# @param [String]
|
|
338
|
-
# @param [::Boolean]
|
|
349
|
+
# @param der [String]
|
|
350
|
+
# @param ber [::Boolean]
|
|
339
351
|
# @return [void]
|
|
340
352
|
# @since 0.15.0 was private before
|
|
341
353
|
def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
|
|
@@ -344,16 +356,21 @@ module RASN1
|
|
|
344
356
|
|
|
345
357
|
private
|
|
346
358
|
|
|
359
|
+
# @private Tracer private API
|
|
360
|
+
# @return [String]
|
|
347
361
|
def trace_real
|
|
348
|
-
encoded_id =
|
|
362
|
+
encoded_id = bin2hex(encode_identifier_octets)
|
|
349
363
|
data_length = raw_data.length
|
|
350
|
-
encoded_length =
|
|
364
|
+
encoded_length = bin2hex(raw_length)
|
|
351
365
|
msg = msg_type
|
|
352
366
|
msg << " (0x#{encoded_id}),"
|
|
353
367
|
msg << " len: #{data_length} (0x#{encoded_length})"
|
|
354
368
|
msg << trace_data
|
|
355
369
|
end
|
|
356
370
|
|
|
371
|
+
# @private Tracer private API
|
|
372
|
+
# @param data [String,nil]
|
|
373
|
+
# @return [String]
|
|
357
374
|
def trace_data(data=nil)
|
|
358
375
|
byte_count = 0
|
|
359
376
|
data ||= raw_data
|
|
@@ -372,24 +389,33 @@ module RASN1
|
|
|
372
389
|
lines.map(&:rstrip).join << "\n"
|
|
373
390
|
end
|
|
374
391
|
|
|
392
|
+
# @private Tracer private API
|
|
393
|
+
# @param count [Integer]
|
|
394
|
+
# @return [String]
|
|
375
395
|
def trace_format_new_data_line(count)
|
|
376
396
|
head_line = RASN1.tracer.indent(RASN1.tracer.tracing_level + 1)
|
|
377
397
|
("\n#{head_line}%04x " % count) << ' ' * 68
|
|
378
398
|
end
|
|
379
399
|
|
|
400
|
+
# @private Tracer private API
|
|
401
|
+
# @param byte_count [Integer]
|
|
402
|
+
# @param byte_count_mul [Integer]
|
|
403
|
+
# @param offset [Integer]
|
|
404
|
+
# @return [Integer]
|
|
380
405
|
def compute_trace_index(byte_count, byte_count_mul=1, offset=0)
|
|
381
406
|
base_idx = 7 + RASN1.tracer.indent(RASN1.tracer.tracing_level + 1).length
|
|
382
407
|
base_idx + offset + (byte_count % 16) * byte_count_mul
|
|
383
408
|
end
|
|
384
409
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
end
|
|
388
|
-
|
|
410
|
+
# Give ASN.1 tag class as a string. Universal class is returned as an empty string.
|
|
411
|
+
# @return [String]
|
|
389
412
|
def asn1_class_to_s
|
|
390
413
|
asn1_class == :universal ? '' : asn1_class.to_s.upcase << ' '
|
|
391
414
|
end
|
|
392
415
|
|
|
416
|
+
# @private Tracer private API
|
|
417
|
+
# @param no_id [Boolean] if +true+, do not show id
|
|
418
|
+
# @return [String]
|
|
393
419
|
def msg_type(no_id: false)
|
|
394
420
|
msg = name.nil? ? +'' : "#{name} "
|
|
395
421
|
msg << "[ #{asn1_class_to_s}#{id} ] " unless no_id
|
|
@@ -405,6 +431,8 @@ module RASN1
|
|
|
405
431
|
msg
|
|
406
432
|
end
|
|
407
433
|
|
|
434
|
+
# Return a byte with P/C bit set accordingly to self
|
|
435
|
+
# @return [Integer]
|
|
408
436
|
def pc_bit
|
|
409
437
|
if @constructed.nil?
|
|
410
438
|
self.class.const_get(:ASN1_PC)
|
|
@@ -415,6 +443,9 @@ module RASN1
|
|
|
415
443
|
end
|
|
416
444
|
end
|
|
417
445
|
|
|
446
|
+
# Common part for {#inspect}
|
|
447
|
+
# @param level [Integer]
|
|
448
|
+
# @return [String]
|
|
418
449
|
def common_inspect(level)
|
|
419
450
|
lvl = [level, 0].max
|
|
420
451
|
str = ' ' * lvl
|
|
@@ -425,6 +456,8 @@ module RASN1
|
|
|
425
456
|
str << "#{type}:"
|
|
426
457
|
end
|
|
427
458
|
|
|
459
|
+
# Value part for {#inspect}
|
|
460
|
+
# @return [String]
|
|
428
461
|
def inspect_value
|
|
429
462
|
if value?
|
|
430
463
|
value.inspect
|
|
@@ -433,6 +466,8 @@ module RASN1
|
|
|
433
466
|
end
|
|
434
467
|
end
|
|
435
468
|
|
|
469
|
+
# Serialize value to DER encoding
|
|
470
|
+
# @return [String]
|
|
436
471
|
def value_to_der
|
|
437
472
|
case @value
|
|
438
473
|
when Base
|
|
@@ -442,6 +477,10 @@ module RASN1
|
|
|
442
477
|
end
|
|
443
478
|
end
|
|
444
479
|
|
|
480
|
+
# Set class
|
|
481
|
+
# @param asn1_class [Symbol, nil]
|
|
482
|
+
# @return [Symbol] ASN.1 symbol class from {CLASSES}
|
|
483
|
+
# @raise [ClassError]
|
|
445
484
|
def set_class(asn1_class) # rubocop:disable Naming/AccessorMethodName
|
|
446
485
|
case asn1_class
|
|
447
486
|
when nil
|
|
@@ -455,16 +494,28 @@ module RASN1
|
|
|
455
494
|
end
|
|
456
495
|
end
|
|
457
496
|
|
|
497
|
+
# Set @optional
|
|
498
|
+
# @param optional [Object]
|
|
499
|
+
# @return [Boolean]
|
|
458
500
|
def set_optional(optional) # rubocop:disable Naming/AccessorMethodName
|
|
459
501
|
@optional = !!optional
|
|
460
502
|
end
|
|
461
503
|
|
|
504
|
+
# Set @default
|
|
505
|
+
# @param default [Object] default value to set
|
|
506
|
+
# @return [Object] +default+
|
|
462
507
|
def set_default(default) # rubocop:disable Naming/AccessorMethodName
|
|
463
508
|
@default = default
|
|
464
509
|
end
|
|
465
510
|
|
|
466
511
|
# handle undocumented option +:tag_value+, used internally by
|
|
467
512
|
# {RASN1.parse} to parse non-universal class tags.
|
|
513
|
+
# @param options [Hash]
|
|
514
|
+
# @option options [Boolean] :constructed
|
|
515
|
+
# @option options [Integer] :explicit
|
|
516
|
+
# @option options [Integer] :implicit
|
|
517
|
+
# @option options [Integer] :tag_value
|
|
518
|
+
# @return [void]
|
|
468
519
|
def set_tag(options) # rubocop:disable Naming/AccessorMethodName
|
|
469
520
|
@constructed = options[:constructed]
|
|
470
521
|
if options[:explicit]
|
|
@@ -480,6 +531,9 @@ module RASN1
|
|
|
480
531
|
@asn1_class = :context if defined?(@tag) && (@asn1_class == :universal)
|
|
481
532
|
end
|
|
482
533
|
|
|
534
|
+
# Set value
|
|
535
|
+
# @param value [Object]
|
|
536
|
+
# @return [Object] +value+ or {#void_value} if +value+ is +nil
|
|
483
537
|
def set_value(value) # rubocop:disable Naming/AccessorMethodName
|
|
484
538
|
if value.nil?
|
|
485
539
|
@no_value = true
|
|
@@ -491,6 +545,8 @@ module RASN1
|
|
|
491
545
|
value
|
|
492
546
|
end
|
|
493
547
|
|
|
548
|
+
# Encode +self+ to BER encoding
|
|
549
|
+
# @return [String]
|
|
494
550
|
def build
|
|
495
551
|
if can_build?
|
|
496
552
|
if explicit?
|
|
@@ -506,16 +562,22 @@ module RASN1
|
|
|
506
562
|
end
|
|
507
563
|
end
|
|
508
564
|
|
|
565
|
+
# Return ID part of tag
|
|
566
|
+
# @return [Integer]
|
|
509
567
|
def id_value
|
|
510
568
|
return @id_value if defined?(@id_value) && !@id_value.nil?
|
|
511
569
|
|
|
512
570
|
self.class.const_get(:ID)
|
|
513
571
|
end
|
|
514
572
|
|
|
573
|
+
# Encode ID
|
|
574
|
+
# @return [String]
|
|
515
575
|
def encode_identifier_octets
|
|
516
576
|
id2octets.pack('C*')
|
|
517
577
|
end
|
|
518
578
|
|
|
579
|
+
# Generate an aray of bytes from ID
|
|
580
|
+
# @return [Array<Integer>]
|
|
519
581
|
def id2octets
|
|
520
582
|
first_octet = CLASSES[asn1_class] | pc_bit
|
|
521
583
|
if id < MULTI_OCTETS_ID
|
|
@@ -528,6 +590,8 @@ module RASN1
|
|
|
528
590
|
# Encode an unsigned integer on multiple octets.
|
|
529
591
|
# Value is encoded on bit 6-0 of each octet, bit 7(MSB) indicates wether
|
|
530
592
|
# further octets follow.
|
|
593
|
+
# @param value [Integer]
|
|
594
|
+
# @return [Array<Integer>]
|
|
531
595
|
def unsigned_to_chained_octets(value)
|
|
532
596
|
ary = []
|
|
533
597
|
while value.positive?
|
|
@@ -538,6 +602,9 @@ module RASN1
|
|
|
538
602
|
ary
|
|
539
603
|
end
|
|
540
604
|
|
|
605
|
+
# Encode size to bytes
|
|
606
|
+
# @param size [integer]
|
|
607
|
+
# @return [String]
|
|
541
608
|
def encode_size(size)
|
|
542
609
|
if size >= INDEFINITE_LENGTH
|
|
543
610
|
bytes = []
|
|
@@ -554,6 +621,7 @@ module RASN1
|
|
|
554
621
|
end
|
|
555
622
|
|
|
556
623
|
# Check ID from +der+ is the one expected
|
|
624
|
+
# @param der [String] DER binary data
|
|
557
625
|
# @return [Boolean] +true+ is ID is expected, +false+ if it is not but +self+ is {#optional?}
|
|
558
626
|
# or has a {#default} value.
|
|
559
627
|
# @raise [ASN1Error] ID was not expected, is not optional and has no default value
|
|
@@ -573,6 +641,10 @@ module RASN1
|
|
|
573
641
|
false
|
|
574
642
|
end
|
|
575
643
|
|
|
644
|
+
# Extract data from DER/BER binary string
|
|
645
|
+
# @param der [String]
|
|
646
|
+
# @param ber [Boolean] +false+ => DER encoding, +true+ => BER encoding
|
|
647
|
+
# @return [Array(Integer, String)] Tuple of total element length in bytes and its data
|
|
576
648
|
def get_data(der, ber)
|
|
577
649
|
return [0, ''] if der.nil? || der.empty?
|
|
578
650
|
|
|
@@ -588,6 +660,10 @@ module RASN1
|
|
|
588
660
|
[total_length, data]
|
|
589
661
|
end
|
|
590
662
|
|
|
663
|
+
# Extract length of element from DER/BER binary string
|
|
664
|
+
# @param der [String]
|
|
665
|
+
# @param ber [Boolean] +false+ => DER encoding, +true+ => BER encoding
|
|
666
|
+
# @return [Array(Integer, Integer)] Tuple of length of data and length of length field, in bytes
|
|
591
667
|
def get_length(der, ber)
|
|
592
668
|
length = der.unpack1('C').to_i
|
|
593
669
|
length_length = 0
|
|
@@ -603,6 +679,9 @@ module RASN1
|
|
|
603
679
|
[length, length_length]
|
|
604
680
|
end
|
|
605
681
|
|
|
682
|
+
# @param ber [Boolean] +false+ => DER encoding, +true+ => BER encoding
|
|
683
|
+
# @raise [ASN1Error] indefinite length and primitive type or DER encoding
|
|
684
|
+
# @raise [NotImplementedError] indefinite length and BER encoding
|
|
606
685
|
def raise_on_indefinite_length(ber)
|
|
607
686
|
if primitive?
|
|
608
687
|
raise ASN1Error, "malformed #{type}: indefinite length " \
|
|
@@ -614,16 +693,24 @@ module RASN1
|
|
|
614
693
|
end
|
|
615
694
|
end
|
|
616
695
|
|
|
696
|
+
# Return a new object of explicit type class
|
|
697
|
+
# @return [Types::Base]
|
|
617
698
|
def explicit_type
|
|
618
699
|
self.class.new(name: name)
|
|
619
700
|
end
|
|
620
701
|
|
|
702
|
+
# Raise bad id error
|
|
703
|
+
# @param der [String] DER/BER data
|
|
704
|
+
# @return [void]
|
|
705
|
+
# @raise [ASN1Error]
|
|
621
706
|
def raise_id_error(der)
|
|
622
707
|
msg = name.nil? ? +'' : "#{name}: "
|
|
623
708
|
msg << "Expected #{self2name} but get #{der2name(der)}"
|
|
624
709
|
raise ASN1Error, msg
|
|
625
710
|
end
|
|
626
711
|
|
|
712
|
+
# Return human-readable tag name for self
|
|
713
|
+
# @return [String]
|
|
627
714
|
def self2name
|
|
628
715
|
name = "#{asn1_class.to_s.upcase} #{constructed? ? 'CONSTRUCTED' : 'PRIMITIVE'}"
|
|
629
716
|
if implicit? || explicit?
|
|
@@ -633,6 +720,9 @@ module RASN1
|
|
|
633
720
|
end
|
|
634
721
|
end
|
|
635
722
|
|
|
723
|
+
# Return human-readable tag name for given +der+
|
|
724
|
+
# @param der [String] DER/BER data
|
|
725
|
+
# @return [String]
|
|
636
726
|
def der2name(der)
|
|
637
727
|
return 'no ID' if der.nil? || der.empty?
|
|
638
728
|
|
|
@@ -642,12 +732,18 @@ module RASN1
|
|
|
642
732
|
name << " #{type.nil? ? '0x%X (0x%s)' % [id, bin2hex(der[0...id_size])] : type.encoded_type}"
|
|
643
733
|
end
|
|
644
734
|
|
|
735
|
+
# Return RASN1 class associated with +id+
|
|
736
|
+
# @param id [Integer]
|
|
737
|
+
# @return [Class,nil]
|
|
645
738
|
def find_type(id)
|
|
646
739
|
Types.constants.map { |c| Types.const_get(c) }
|
|
647
740
|
.select { |klass| klass < Primitive || klass < Constructed }
|
|
648
741
|
.find { |klass| id == klass::ID }
|
|
649
742
|
end
|
|
650
743
|
|
|
744
|
+
# Unpack given binary string to hex string
|
|
745
|
+
# @param str [String] binary string
|
|
746
|
+
# @return [String] hex string
|
|
651
747
|
def bin2hex(str)
|
|
652
748
|
str.unpack1('H*')
|
|
653
749
|
end
|
|
@@ -9,7 +9,18 @@
|
|
|
9
9
|
module RASN1
|
|
10
10
|
module Types
|
|
11
11
|
# ASN.1 Bit String
|
|
12
|
+
#
|
|
13
|
+
# A BIT STRING is a primitive ASN.1 type, able to embbed data whose length is not multiple of a byte.
|
|
14
|
+
#
|
|
15
|
+
# To specify a non byte multiple length, +:bit_length+ option must be used.
|
|
16
|
+
#
|
|
17
|
+
# @example Simple bit string
|
|
18
|
+
# # A 4-bit length bit string, with value 1000b
|
|
19
|
+
# bs = RASN1::Types::BitString.new(value: "\x80", bit_length: 4)
|
|
20
|
+
# # As DER/BER encode data on bytes, such encodings specify unused part in binary string
|
|
21
|
+
# bs.to_der #=> "\x03\x02\x04\x80"
|
|
12
22
|
# @author Sylvain Daubert
|
|
23
|
+
# @author LemonTree55
|
|
13
24
|
class BitString < Primitive
|
|
14
25
|
# BitString id value
|
|
15
26
|
ID = 3
|
|
@@ -17,10 +28,9 @@ module RASN1
|
|
|
17
28
|
# @return [Integer]
|
|
18
29
|
attr_writer :bit_length
|
|
19
30
|
|
|
20
|
-
#
|
|
31
|
+
# @!macro type_initialize
|
|
21
32
|
# @option options [Object] :bit_length default bit_length value. Should be
|
|
22
33
|
# present if +:default+ is set
|
|
23
|
-
# @see Base#initialize common options to all ASN.1 types
|
|
24
34
|
def initialize(options={})
|
|
25
35
|
super
|
|
26
36
|
if @default
|
|
@@ -40,7 +50,7 @@ module RASN1
|
|
|
40
50
|
end
|
|
41
51
|
end
|
|
42
52
|
|
|
43
|
-
# @param [Integer]
|
|
53
|
+
# @param level [Integer]
|
|
44
54
|
# @return [String]
|
|
45
55
|
def inspect(level=0)
|
|
46
56
|
str = common_inspect(level)
|
|
@@ -55,8 +65,8 @@ module RASN1
|
|
|
55
65
|
end
|
|
56
66
|
|
|
57
67
|
# Make value from DER/BER string. Also set {#bit_length}.
|
|
58
|
-
# @param [String]
|
|
59
|
-
# @param [::Boolean]
|
|
68
|
+
# @param der [String]
|
|
69
|
+
# @param ber [::Boolean]
|
|
60
70
|
# @return [void]
|
|
61
71
|
# @see Types::Base#der_to_value
|
|
62
72
|
def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
|
|
@@ -70,6 +80,7 @@ module RASN1
|
|
|
70
80
|
|
|
71
81
|
# @author Sylvain Daubert
|
|
72
82
|
# @author adfoster-r7
|
|
83
|
+
# @return [String]
|
|
73
84
|
def value_to_der
|
|
74
85
|
raise ASN1Error, "#{@name}: bit length is not set" if bit_length.nil?
|
|
75
86
|
|
|
@@ -89,6 +100,7 @@ module RASN1
|
|
|
89
100
|
der
|
|
90
101
|
end
|
|
91
102
|
|
|
103
|
+
# @return [String]
|
|
92
104
|
def generate_value_with_correct_length
|
|
93
105
|
value = (@value || '').dup.force_encoding('BINARY')
|
|
94
106
|
value << "\x00".b while value.length * 8 < @bit_length.to_i
|
|
@@ -98,6 +110,7 @@ module RASN1
|
|
|
98
110
|
value[0, max_len].to_s
|
|
99
111
|
end
|
|
100
112
|
|
|
113
|
+
# @return [BitString]
|
|
101
114
|
def explicit_type
|
|
102
115
|
self.class.new(name: name, value: @value, bit_length: @bit_length)
|
|
103
116
|
end
|
data/lib/rasn1/types/boolean.rb
CHANGED
|
@@ -9,7 +9,16 @@
|
|
|
9
9
|
module RASN1
|
|
10
10
|
module Types
|
|
11
11
|
# ASN.1 Boolean
|
|
12
|
+
#
|
|
13
|
+
# BOOLEAN is a primitive type to handle true or false values.
|
|
14
|
+
# @example Booelan
|
|
15
|
+
# bool = RASN1::Types::Boolean.new(value: true)
|
|
16
|
+
# bool2 = RASN1.parse(bool.to_der)
|
|
17
|
+
# bool2.class #=> RASN1::Types::Boolean
|
|
18
|
+
# bool3.value #=> true
|
|
19
|
+
#
|
|
12
20
|
# @author Sylvain Daubert
|
|
21
|
+
# @author LemonTree55
|
|
13
22
|
class Boolean < Primitive
|
|
14
23
|
# Boolean id value
|
|
15
24
|
ID = 0x01
|
|
@@ -25,8 +34,8 @@ module RASN1
|
|
|
25
34
|
end
|
|
26
35
|
|
|
27
36
|
# Make boolean value from DER/BER string.
|
|
28
|
-
# @param [String]
|
|
29
|
-
# @param [::Boolean]
|
|
37
|
+
# @param der [String]
|
|
38
|
+
# @param ber [::Boolean]
|
|
30
39
|
# @return [void]
|
|
31
40
|
# @see Types::Base#der_to_value
|
|
32
41
|
# @raise [ASN1Error] +der+ is not 1-byte long
|
|
@@ -49,14 +58,16 @@ module RASN1
|
|
|
49
58
|
|
|
50
59
|
private
|
|
51
60
|
|
|
61
|
+
# @return [String]
|
|
52
62
|
def value_to_der
|
|
53
63
|
[@value ? DER_TRUE : DER_FALSE].pack('C')
|
|
54
64
|
end
|
|
55
65
|
|
|
66
|
+
# @return [String]
|
|
56
67
|
def trace_data
|
|
57
68
|
return super if explicit?
|
|
58
69
|
|
|
59
|
-
" #{raw_data == "\x00".b ? 'FALSE' : 'TRUE'} (0x#{raw_data
|
|
70
|
+
" #{raw_data == "\x00".b ? 'FALSE' : 'TRUE'} (0x#{bin2hex(raw_data)})"
|
|
60
71
|
end
|
|
61
72
|
end
|
|
62
73
|
end
|