rasn2 0.16.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 +7 -0
- data/LICENSE +22 -0
- data/README.md +4 -0
- data/lib/rasn1/errors.rb +55 -0
- data/lib/rasn1/helpers/colorize.rb +76 -0
- data/lib/rasn1/model.rb +831 -0
- data/lib/rasn1/schema_parser.rb +470 -0
- data/lib/rasn1/tracer.rb +200 -0
- data/lib/rasn1/types/any.rb +98 -0
- data/lib/rasn1/types/base.rb +675 -0
- data/lib/rasn1/types/bit_string.rb +100 -0
- data/lib/rasn1/types/bmp_string.rb +22 -0
- data/lib/rasn1/types/boolean.rb +57 -0
- data/lib/rasn1/types/choice.rb +158 -0
- data/lib/rasn1/types/constrained.rb +51 -0
- data/lib/rasn1/types/constructed.rb +51 -0
- data/lib/rasn1/types/enumerated.rb +44 -0
- data/lib/rasn1/types/generalized_time.rb +156 -0
- data/lib/rasn1/types/ia5_string.rb +21 -0
- data/lib/rasn1/types/integer.rb +166 -0
- data/lib/rasn1/types/null.rb +43 -0
- data/lib/rasn1/types/numeric_string.rb +41 -0
- data/lib/rasn1/types/object_id.rb +64 -0
- data/lib/rasn1/types/octet_string.rb +52 -0
- data/lib/rasn1/types/primitive.rb +13 -0
- data/lib/rasn1/types/printable_string.rb +42 -0
- data/lib/rasn1/types/sequence.rb +105 -0
- data/lib/rasn1/types/sequence_of.rb +199 -0
- data/lib/rasn1/types/set.rb +28 -0
- data/lib/rasn1/types/set_of.rb +18 -0
- data/lib/rasn1/types/tag.rb +189 -0
- data/lib/rasn1/types/universal_string.rb +22 -0
- data/lib/rasn1/types/utc_time.rb +67 -0
- data/lib/rasn1/types/utf8_string.rb +21 -0
- data/lib/rasn1/types/visible_string.rb +30 -0
- data/lib/rasn1/types.rb +149 -0
- data/lib/rasn1/value_notation.rb +256 -0
- data/lib/rasn1/version.rb +6 -0
- data/lib/rasn1/wrapper.rb +279 -0
- data/lib/rasn1.rb +51 -0
- metadata +123 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RASN1
|
|
4
|
+
module Types
|
|
5
|
+
# ASN.1 Integer
|
|
6
|
+
# @author Sylvain Daubert
|
|
7
|
+
class Integer < Primitive
|
|
8
|
+
# @return [Hash,nil]
|
|
9
|
+
attr_reader :enum
|
|
10
|
+
|
|
11
|
+
# Integer id value
|
|
12
|
+
ID = 2
|
|
13
|
+
|
|
14
|
+
# @option options [Hash] :enum enumeration hash. Keys are names, and values
|
|
15
|
+
# are integers.
|
|
16
|
+
# @raise [EnumeratedError] +:default+ value is unknown when +:enum+ key is present
|
|
17
|
+
# @see Base#initialize common options to all ASN.1 types
|
|
18
|
+
def initialize(options={})
|
|
19
|
+
super
|
|
20
|
+
initialize_enum(@options[:enum])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @param [Integer,String,Symbol,nil] val
|
|
24
|
+
# @return [void]
|
|
25
|
+
def value=(val)
|
|
26
|
+
@no_value = false
|
|
27
|
+
case val
|
|
28
|
+
when String, Symbol
|
|
29
|
+
value_from_string_or_symbol(val)
|
|
30
|
+
when ::Integer
|
|
31
|
+
value_from_integer(val)
|
|
32
|
+
when nil
|
|
33
|
+
@no_value = true
|
|
34
|
+
@value = void_value
|
|
35
|
+
else
|
|
36
|
+
raise EnumeratedError, "#{@name}: not in enumeration"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [Integer]
|
|
41
|
+
def void_value
|
|
42
|
+
0
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Integer value
|
|
46
|
+
# @return [Integer]
|
|
47
|
+
def to_i
|
|
48
|
+
val = value? ? @value : @default
|
|
49
|
+
case val
|
|
50
|
+
when String, Symbol
|
|
51
|
+
@enum[val]
|
|
52
|
+
else
|
|
53
|
+
val || 0
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Make integer value from +der+ string.
|
|
58
|
+
# @param [String] der
|
|
59
|
+
# @param [::Boolean] ber
|
|
60
|
+
# @return [void]
|
|
61
|
+
def der_to_value(der, ber: false)
|
|
62
|
+
int_value = der_to_int_value(der, ber: ber)
|
|
63
|
+
@value = if @enum.empty?
|
|
64
|
+
int_value
|
|
65
|
+
else
|
|
66
|
+
int_to_enum(int_value)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def initialize_enum(enum)
|
|
73
|
+
@enum = enum || {}
|
|
74
|
+
return if @enum.empty?
|
|
75
|
+
|
|
76
|
+
# To ensure @value has the correct type
|
|
77
|
+
self.value = @value if value?
|
|
78
|
+
|
|
79
|
+
check_enum_default
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def check_enum_default
|
|
83
|
+
case @default
|
|
84
|
+
when String, Symbol
|
|
85
|
+
raise EnumeratedError, "#{@name}: unknwon enumerated default value #@{default}" unless @enum.key?(@default)
|
|
86
|
+
when ::Integer
|
|
87
|
+
raise EnumeratedError, "#{@name}: default value #@{default} not in enumeration" unless @enum.value?(@default)
|
|
88
|
+
|
|
89
|
+
@default = @enum.key(@default)
|
|
90
|
+
when nil
|
|
91
|
+
else
|
|
92
|
+
raise TypeError, "#{@name}: #{@default.class} not handled as default value"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def value_from_string_or_symbol(val)
|
|
97
|
+
raise EnumeratedError, "#{@name} has no :enum" if @enum.empty?
|
|
98
|
+
raise EnumeratedError, "#{@name}: unknwon enumerated value #{val}" unless @enum.key? val
|
|
99
|
+
|
|
100
|
+
@value = val
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def value_from_integer(val)
|
|
104
|
+
if @enum.empty?
|
|
105
|
+
@value = val
|
|
106
|
+
elsif @enum.value? val
|
|
107
|
+
@value = @enum.key(val)
|
|
108
|
+
else
|
|
109
|
+
raise EnumeratedError, "#{@name}: #{val} not in enumeration"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def int_value_to_der(value)
|
|
114
|
+
size = compute_size(value)
|
|
115
|
+
comp_value = value >= 0 ? value : (~(-value) + 1) & ((1 << (size * 8)) - 1)
|
|
116
|
+
ary = comp_value.digits(256)
|
|
117
|
+
# v is > 0 and its MSBit is 1. Add a 0 byte to mark it as positive
|
|
118
|
+
ary << 0 if value.positive? && (value >> (size * 8 - 1) == 1)
|
|
119
|
+
ary.reverse.pack('C*')
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def compute_size(value)
|
|
123
|
+
size = value.bit_length / 8 + ((value.bit_length % 8).positive? ? 1 : 0)
|
|
124
|
+
size = 1 if size.zero?
|
|
125
|
+
size
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def value_to_der
|
|
129
|
+
case @value
|
|
130
|
+
when String, Symbol
|
|
131
|
+
int_value_to_der(@enum[@value])
|
|
132
|
+
when ::Integer
|
|
133
|
+
int_value_to_der(@value)
|
|
134
|
+
else
|
|
135
|
+
raise TypeError, "#{@name}: #{@value.class} not handled"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def der_to_int_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
|
|
140
|
+
ary = der.unpack('C*')
|
|
141
|
+
v = ary.reduce(0) { |len, b| (len << 8) | b }
|
|
142
|
+
v = -((~v & ((1 << v.bit_length) - 1)) + 1) if ary[0] & 0x80 == 0x80
|
|
143
|
+
v
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def int_to_enum(int, check_enum: true)
|
|
147
|
+
raise EnumeratedError, "#{@name}: value #{int} not in enumeration" if check_enum && !@enum.value?(int)
|
|
148
|
+
|
|
149
|
+
@enum.key(int) || int
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def explicit_type
|
|
153
|
+
self.class.new(name: name, enum: enum)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def trace_data
|
|
157
|
+
return super if explicit?
|
|
158
|
+
i = der_to_int_value(raw_data)
|
|
159
|
+
return " #{int_with_hex(i, raw_data.unpack1('H*'))}" if @enum.empty?
|
|
160
|
+
|
|
161
|
+
v = int_to_enum(i, check_enum: false)
|
|
162
|
+
" #{colorize_enum(v, raw_data)}"
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RASN1
|
|
4
|
+
module Types
|
|
5
|
+
# ASN.1 Null
|
|
6
|
+
# @author Sylvain Daubert
|
|
7
|
+
class Null < Primitive
|
|
8
|
+
# Null id value
|
|
9
|
+
ID = 0x05
|
|
10
|
+
|
|
11
|
+
# @return [String]
|
|
12
|
+
def inspect(level=0)
|
|
13
|
+
str = common_inspect(level)[0..-2] # remove terminal ':'
|
|
14
|
+
str << ' OPTIONAL' if optional?
|
|
15
|
+
str
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @return [Boolean]
|
|
19
|
+
# Build only if not optional
|
|
20
|
+
def can_build?
|
|
21
|
+
!optional?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Check +der+ string
|
|
25
|
+
# @param [String] der
|
|
26
|
+
# @param [::Boolean] ber
|
|
27
|
+
# @return [void]
|
|
28
|
+
# @raise [ASN1Error] +der+ is not empty
|
|
29
|
+
def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
|
|
30
|
+
raise ASN1Error, 'NULL should not have content!' if der.length.positive?
|
|
31
|
+
|
|
32
|
+
@no_value = true
|
|
33
|
+
@value = void_value
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def value_to_der
|
|
39
|
+
''
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RASN1
|
|
4
|
+
module Types
|
|
5
|
+
# ASN.1 Numeric String
|
|
6
|
+
# @author Sylvain Daubert
|
|
7
|
+
class NumericString < OctetString
|
|
8
|
+
# NumericString id value
|
|
9
|
+
ID = 18
|
|
10
|
+
# Invalid characters in NumericString
|
|
11
|
+
INVALID_CHARS = /([^0-9 ])/
|
|
12
|
+
|
|
13
|
+
# Get ASN.1 type
|
|
14
|
+
# @return [String]
|
|
15
|
+
def self.type
|
|
16
|
+
'NumericString'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Make string value from +der+ string
|
|
20
|
+
# @param [String] der
|
|
21
|
+
# @param [::Boolean] ber
|
|
22
|
+
# @return [void]
|
|
23
|
+
# @raise [ASN1Error] invalid characters detected
|
|
24
|
+
def der_to_value(der, ber: false)
|
|
25
|
+
super
|
|
26
|
+
check_characters
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def value_to_der
|
|
32
|
+
check_characters
|
|
33
|
+
@value.to_s.b
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def check_characters
|
|
37
|
+
raise ASN1Error, "NUMERIC STRING #{@name}: invalid character: '#{$1}'" if @value.to_s =~ INVALID_CHARS
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RASN1
|
|
4
|
+
module Types
|
|
5
|
+
# ASN.1 Object ID
|
|
6
|
+
# @author Sylvain Daubert
|
|
7
|
+
# @author LemonTree55
|
|
8
|
+
class ObjectId < Primitive
|
|
9
|
+
# ObjectId id value
|
|
10
|
+
ID = 6
|
|
11
|
+
|
|
12
|
+
# Make object id value from +der+ string
|
|
13
|
+
# @param [String] der
|
|
14
|
+
# @param [::Boolean] ber
|
|
15
|
+
# @return [void]
|
|
16
|
+
def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
|
|
17
|
+
bytes = der.unpack('C*')
|
|
18
|
+
|
|
19
|
+
ids = []
|
|
20
|
+
current_id = 0
|
|
21
|
+
bytes.each do |byte|
|
|
22
|
+
current_id = (current_id << 7) | (byte & 0x7f)
|
|
23
|
+
if byte.nobits?(0x80)
|
|
24
|
+
ids << current_id
|
|
25
|
+
current_id = 0
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
first_id = [2, ids.first / 40].min
|
|
30
|
+
second_id = ids.first - first_id * 40
|
|
31
|
+
ids[0..0] = [first_id, second_id]
|
|
32
|
+
|
|
33
|
+
@value = ids.join('.')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
# @raise [ASN1Error]
|
|
39
|
+
def value_to_der
|
|
40
|
+
ids = @value.to_s.split('.').map(&:to_i)
|
|
41
|
+
|
|
42
|
+
check_first_ids(ids)
|
|
43
|
+
|
|
44
|
+
ids[0, 2] = ids[0] * 40 + ids[1]
|
|
45
|
+
octets = []
|
|
46
|
+
ids.each do |v|
|
|
47
|
+
if v < 128
|
|
48
|
+
octets << v
|
|
49
|
+
else
|
|
50
|
+
octets.concat(unsigned_to_chained_octets(v))
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
octets.pack('C*')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @param [Array[::Integer]] ids
|
|
57
|
+
# @raise [ASN1Error]
|
|
58
|
+
def check_first_ids(ids)
|
|
59
|
+
raise ASN1Error, "OBJECT ID #{@name}: first subidentifier should be less than 3" if ids[0] > 2
|
|
60
|
+
raise ASN1Error, "OBJECT ID #{@name}: second subidentifier should be less than 40" if (ids[0] < 2) && (ids[1] > 39)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RASN1
|
|
4
|
+
module Types
|
|
5
|
+
# ASN.1 Octet String
|
|
6
|
+
#
|
|
7
|
+
# An OCTET STRINT may contain another primtive object:
|
|
8
|
+
# os = OctetString.new
|
|
9
|
+
# int = Integer.new
|
|
10
|
+
# int.value = 12
|
|
11
|
+
# os.value = int
|
|
12
|
+
# os.to_der # => DER string with INTEGER in OCTET STRING
|
|
13
|
+
# @author Sylvain Daubert
|
|
14
|
+
class OctetString < Primitive
|
|
15
|
+
# OctetString id value
|
|
16
|
+
ID = 4
|
|
17
|
+
|
|
18
|
+
# @param [::Integer] level
|
|
19
|
+
# @return [String]
|
|
20
|
+
def inspect(level=0)
|
|
21
|
+
str = common_inspect(level)
|
|
22
|
+
str << " #{value.inspect}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Make string value from +der+ string. Force encoding to UTF-8
|
|
26
|
+
# @param [String] der
|
|
27
|
+
# @param [::Boolean] ber
|
|
28
|
+
# @return [void]
|
|
29
|
+
# @since 0.15.0 Handle ENCODING constant, if defined by subclass
|
|
30
|
+
def der_to_value(der, ber: false)
|
|
31
|
+
klass = self.class
|
|
32
|
+
if klass.const_defined?(:ENCODING)
|
|
33
|
+
@value = der.to_s.dup.force_encoding(klass.const_get(:ENCODING))
|
|
34
|
+
else
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# @since 0.15.0 Handle ENCODING constant, if defined by subclass
|
|
42
|
+
def value_to_der
|
|
43
|
+
klass = self.class
|
|
44
|
+
if klass.const_defined?(:ENCODING)
|
|
45
|
+
@value.to_s.encode(klass.const_get(:ENCODING)).b
|
|
46
|
+
else
|
|
47
|
+
super
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RASN1
|
|
4
|
+
module Types
|
|
5
|
+
# @abstract This class SHOULD be used as base class for all ASN.1 primitive
|
|
6
|
+
# types.
|
|
7
|
+
# @author Sylvain Daubert
|
|
8
|
+
class Primitive < Base
|
|
9
|
+
# Primitive value
|
|
10
|
+
ASN1_PC = 0x00
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RASN1
|
|
4
|
+
module Types
|
|
5
|
+
# ASN.1 Printable String
|
|
6
|
+
# @author Sylvain Daubert
|
|
7
|
+
class PrintableString < OctetString
|
|
8
|
+
# PrintableString id value
|
|
9
|
+
ID = 19
|
|
10
|
+
# Invalid characters in PrintableString
|
|
11
|
+
INVALID_CHARS = %r{([^a-zA-Z0-9 '=()+,\-./:?])}
|
|
12
|
+
|
|
13
|
+
# Get ASN.1 type
|
|
14
|
+
# @return [String]
|
|
15
|
+
def self.type
|
|
16
|
+
'PrintableString'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Make string value from +der+ string
|
|
20
|
+
# @param [String] der
|
|
21
|
+
# @param [::Boolean] ber
|
|
22
|
+
# @return [void]
|
|
23
|
+
# @raise [ASN1Error] invalid characters detected
|
|
24
|
+
def der_to_value(der, ber: false)
|
|
25
|
+
super
|
|
26
|
+
check_characters
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def value_to_der
|
|
32
|
+
check_characters
|
|
33
|
+
@value.to_s.b
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def check_characters
|
|
37
|
+
m = @value.to_s.match(INVALID_CHARS)
|
|
38
|
+
raise ASN1Error, "PRINTABLE STRING #{@name}: invalid character: '#{m[1]}'" if m
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RASN1
|
|
4
|
+
module Types
|
|
5
|
+
# ASN.1 sequence
|
|
6
|
+
#
|
|
7
|
+
# A sequence is a collection of another ASN.1 types.
|
|
8
|
+
#
|
|
9
|
+
# To encode this ASN.1 example:
|
|
10
|
+
# Record ::= SEQUENCE {
|
|
11
|
+
# id INTEGER,
|
|
12
|
+
# room [0] INTEGER OPTIONAL,
|
|
13
|
+
# house [1] IMPLICIT INTEGER DEFAULT 0
|
|
14
|
+
# }
|
|
15
|
+
# do:
|
|
16
|
+
# seq = RASN1::Types::Sequence.new
|
|
17
|
+
# seq.value = [
|
|
18
|
+
# RASN1::Types::Integer.new
|
|
19
|
+
# RASN1::Types::Integer.new(explicit: 0, optional: true),
|
|
20
|
+
# RASN1::Types::Integer.new(implicit: 1, default: 0)
|
|
21
|
+
# ]
|
|
22
|
+
#
|
|
23
|
+
# A sequence may also be used without value to not parse sequence content:
|
|
24
|
+
# seq = RASN1::Types::Sequence.new(:seq)
|
|
25
|
+
# seq.parse!(der_string)
|
|
26
|
+
# seq.value # => String
|
|
27
|
+
# @author Sylvain Daubert
|
|
28
|
+
class Sequence < Constructed
|
|
29
|
+
# Sequence id value
|
|
30
|
+
ID = 0x10
|
|
31
|
+
|
|
32
|
+
# @see Base#initialize
|
|
33
|
+
def initialize(options={})
|
|
34
|
+
super
|
|
35
|
+
@no_value = false
|
|
36
|
+
@value ||= []
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Deep copy @value
|
|
40
|
+
def initialize_copy(*)
|
|
41
|
+
super
|
|
42
|
+
@value = case @value
|
|
43
|
+
when Array
|
|
44
|
+
@value.map(&:dup)
|
|
45
|
+
else
|
|
46
|
+
@value.dup
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [Array]
|
|
51
|
+
def void_value
|
|
52
|
+
[]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Get element at index +idx+, or element of name +name+
|
|
56
|
+
# @param [Integer, String, Symbol] idx_or_name
|
|
57
|
+
# @return [Object,nil]
|
|
58
|
+
def [](idx_or_name)
|
|
59
|
+
return unless @value.is_a?(Array)
|
|
60
|
+
|
|
61
|
+
case idx_or_name
|
|
62
|
+
when ::Integer
|
|
63
|
+
@value[idx_or_name.to_i]
|
|
64
|
+
when String, Symbol
|
|
65
|
+
@value.find { |elt| elt.name == idx_or_name }
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Make sequence value from +der+ string
|
|
70
|
+
# @param [String] der
|
|
71
|
+
# @param [::Boolean] ber
|
|
72
|
+
# @return [void]
|
|
73
|
+
def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
|
|
74
|
+
if @value.is_a?(Array) && !@value.empty?
|
|
75
|
+
nb_bytes = 0
|
|
76
|
+
@value.each do |element|
|
|
77
|
+
nb_bytes += element.parse!(der[nb_bytes..])
|
|
78
|
+
end
|
|
79
|
+
else
|
|
80
|
+
@value = der
|
|
81
|
+
der.length
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def value_to_der
|
|
88
|
+
case @value
|
|
89
|
+
when Array
|
|
90
|
+
@value.map(&:to_der).join
|
|
91
|
+
else
|
|
92
|
+
@value.to_s
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def trace_data
|
|
97
|
+
''
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def explicit_type
|
|
101
|
+
self.class.new(name: name, value: @value)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|