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
@@ -1,91 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RASN1
|
2
4
|
module Types
|
3
|
-
|
4
5
|
# ASN.1 Bit String
|
5
6
|
# @author Sylvain Daubert
|
6
7
|
class BitString < Primitive
|
7
|
-
|
8
|
+
# BitString id value
|
9
|
+
ID = 3
|
8
10
|
|
9
11
|
# @param [Integer] bit_length
|
10
12
|
# @return [Integer]
|
11
13
|
attr_writer :bit_length
|
12
14
|
|
13
|
-
# @
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# present if +:default+ is set
|
17
|
-
# @overload initialize(value, options={})
|
18
|
-
# @param [Object] value value to set for this ASN.1 object
|
19
|
-
# @param [Hash] options
|
20
|
-
# @option options [Object] :bit_length default bit_length value. Should be
|
21
|
-
# present if +:default+ is set
|
15
|
+
# @param [Hash] options
|
16
|
+
# @option options [Object] :bit_length default bit_length value. Should be
|
17
|
+
# present if +:default+ is set
|
22
18
|
# @see Base#initialize common options to all ASN.1 types
|
23
|
-
def initialize(
|
19
|
+
def initialize(options={})
|
24
20
|
super
|
25
|
-
opts = value_or_options.is_a?(Hash) ? value_or_options : options
|
26
21
|
if @default
|
27
|
-
if
|
28
|
-
|
29
|
-
|
30
|
-
@default_bit_length = opts[:bit_length]
|
22
|
+
raise ASN1Error, "#{@name}: default bit length is not defined" if @options[:bit_length].nil?
|
23
|
+
|
24
|
+
@default_bit_length = @options[:bit_length]
|
31
25
|
end
|
32
|
-
@bit_length =
|
26
|
+
@bit_length = @options[:bit_length]
|
33
27
|
end
|
34
28
|
|
35
29
|
# Get bit length
|
36
30
|
def bit_length
|
37
|
-
if
|
38
|
-
@default_bit_length
|
39
|
-
else
|
31
|
+
if value?
|
40
32
|
@bit_length
|
33
|
+
else
|
34
|
+
@default_bit_length
|
41
35
|
end
|
42
36
|
end
|
43
37
|
|
44
38
|
# @param [Integer] level
|
45
39
|
# @return [String]
|
46
40
|
def inspect(level=0)
|
47
|
-
str =
|
48
|
-
str <<
|
49
|
-
str << "#{name} " unless @name.nil?
|
50
|
-
str << "#{type}: #{value.inspect} (bit length: #{bit_length})"
|
41
|
+
str = common_inspect(level)
|
42
|
+
str << " #{value.inspect} (bit length: #{bit_length})"
|
51
43
|
end
|
52
44
|
|
53
45
|
private
|
54
46
|
|
55
|
-
def
|
56
|
-
!(!@default.nil?
|
57
|
-
@bit_length == @default_bit_length))
|
58
|
-
!(optional?
|
47
|
+
def can_build?
|
48
|
+
!(!@default.nil? && (!value? || (@value == @default) &&
|
49
|
+
(@bit_length == @default_bit_length))) &&
|
50
|
+
!(optional? && !value?)
|
59
51
|
end
|
60
52
|
|
61
53
|
def value_to_der
|
62
|
-
raise ASN1Error, "
|
54
|
+
raise ASN1Error, "#{@name}: bit length is not set" if bit_length.nil?
|
63
55
|
|
64
|
-
|
65
|
-
@value << "\x00"
|
66
|
-
end
|
67
|
-
@value.force_encoding('BINARY')
|
68
|
-
|
69
|
-
if @value.length * 8 > @bit_length
|
70
|
-
max_len = @bit_length / 8 + (@bit_length % 8 > 0 ? 1 : 0)
|
71
|
-
@value = @value[0, max_len]
|
72
|
-
end
|
56
|
+
value = generate_value_with_correct_length
|
73
57
|
|
74
|
-
unused =
|
75
|
-
der = [unused,
|
58
|
+
unused = value.length * 8 - @bit_length.to_i
|
59
|
+
der = [unused, value].pack('CA*')
|
76
60
|
|
77
|
-
if unused
|
78
|
-
last_byte =
|
61
|
+
if unused.positive?
|
62
|
+
last_byte = value[-1].to_s.unpack1('C').to_i
|
79
63
|
last_byte &= (0xff >> unused) << unused
|
80
64
|
der[-1] = [last_byte].pack('C')
|
81
65
|
end
|
82
66
|
|
67
|
+
@value = value
|
68
|
+
|
83
69
|
der
|
84
70
|
end
|
85
71
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
72
|
+
def generate_value_with_correct_length
|
73
|
+
value = @value || ''
|
74
|
+
value << "\x00" while value.length * 8 < @bit_length.to_i
|
75
|
+
value.force_encoding('BINARY')
|
76
|
+
return value unless value.length * 8 > @bit_length.to_i
|
77
|
+
|
78
|
+
max_len = @bit_length.to_i / 8 + ((@bit_length.to_i % 8).positive? ? 1 : 0)
|
79
|
+
value[0, max_len].to_s
|
80
|
+
end
|
81
|
+
|
82
|
+
def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
|
83
|
+
unused = der.unpack1('C').to_i
|
84
|
+
value = der[1..-1].to_s
|
85
|
+
@bit_length = value.length * 8 - unused
|
86
|
+
@value = value
|
89
87
|
end
|
90
88
|
end
|
91
89
|
end
|
data/lib/rasn1/types/boolean.rb
CHANGED
@@ -1,34 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RASN1
|
2
4
|
module Types
|
3
|
-
|
4
5
|
# ASN.1 Boolean
|
5
6
|
# @author Sylvain Daubert
|
6
7
|
class Boolean < Primitive
|
7
|
-
|
8
|
+
# Boolean id value
|
9
|
+
ID = 0x01
|
10
|
+
|
11
|
+
# @private
|
12
|
+
DER_TRUE = 0xff
|
13
|
+
# @private
|
14
|
+
DER_FALSE = 0
|
15
|
+
|
16
|
+
# @return [false]
|
17
|
+
def void_value
|
18
|
+
false
|
19
|
+
end
|
8
20
|
|
9
21
|
private
|
10
22
|
|
11
23
|
def value_to_der
|
12
|
-
[@value ?
|
24
|
+
[@value ? DER_TRUE : DER_FALSE].pack('C')
|
13
25
|
end
|
14
26
|
|
15
27
|
def der_to_value(der, ber: false)
|
16
|
-
unless der.size == 1
|
17
|
-
raise ASN1Error, "tag #@name: BOOLEAN should have a length of 1"
|
18
|
-
end
|
28
|
+
raise ASN1Error, "tag #{@name}: BOOLEAN should have a length of 1" unless der.size == 1
|
19
29
|
|
20
|
-
bool = der.
|
30
|
+
bool = der.unpack1('C')
|
21
31
|
case bool
|
22
|
-
when
|
32
|
+
when DER_FALSE
|
23
33
|
@value = false
|
24
|
-
when
|
34
|
+
when DER_TRUE
|
25
35
|
@value = true
|
26
36
|
else
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
raise ASN1Error, "tag #@name: bad value 0x%02x for BOOLEAN" % bool
|
31
|
-
end
|
37
|
+
raise ASN1Error, "tag #{@name}: bad value 0x%02x for BOOLEAN" % bool unless ber
|
38
|
+
|
39
|
+
@value = true
|
32
40
|
end
|
33
41
|
end
|
34
42
|
end
|
data/lib/rasn1/types/choice.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RASN1
|
2
4
|
module Types
|
3
|
-
|
4
5
|
# A ASN.1 CHOICE is a choice between different types.
|
5
6
|
#
|
6
7
|
# == Create a CHOICE
|
@@ -31,7 +32,6 @@ module RASN1
|
|
31
32
|
# choice.chosen_value # => "abc"
|
32
33
|
# @author Sylvain Daubert
|
33
34
|
class Choice < Base
|
34
|
-
|
35
35
|
# Chosen type
|
36
36
|
# @return [Integer] index of type in choice value
|
37
37
|
attr_accessor :chosen
|
@@ -41,7 +41,7 @@ module RASN1
|
|
41
41
|
# @param [Object] value
|
42
42
|
# @return [Object] value
|
43
43
|
# @raise [ChoiceError] {#chosen} not set
|
44
|
-
def set_chosen_value(value)
|
44
|
+
def set_chosen_value(value) # rubocop:disable Naming/AccessorMethodName
|
45
45
|
check_chosen
|
46
46
|
@value[@chosen].value = value
|
47
47
|
end
|
@@ -79,7 +79,7 @@ module RASN1
|
|
79
79
|
@value.each_with_index do |element, i|
|
80
80
|
begin
|
81
81
|
@chosen = i
|
82
|
-
nb_bytes = element.parse!(der)
|
82
|
+
nb_bytes = element.parse!(der, ber: ber)
|
83
83
|
parsed = true
|
84
84
|
return nb_bytes
|
85
85
|
rescue ASN1Error
|
@@ -87,19 +87,16 @@ module RASN1
|
|
87
87
|
next
|
88
88
|
end
|
89
89
|
end
|
90
|
-
raise ASN1Error, "CHOICE
|
90
|
+
raise ASN1Error, "CHOICE #{@name}: no type matching #{der.inspect}" unless parsed
|
91
91
|
end
|
92
92
|
|
93
93
|
def inspect(level=0)
|
94
|
-
str =
|
95
|
-
str <<
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
else
|
101
|
-
str << "\n#{@value[@chosen].inspect(level+1)}"
|
102
|
-
end
|
94
|
+
str = common_inspect(level)
|
95
|
+
str << if defined? @chosen
|
96
|
+
"\n#{@value[@chosen].inspect(level + 1)}"
|
97
|
+
else
|
98
|
+
' not chosen!'
|
99
|
+
end
|
103
100
|
end
|
104
101
|
|
105
102
|
private
|
@@ -110,5 +107,3 @@ module RASN1
|
|
110
107
|
end
|
111
108
|
end
|
112
109
|
end
|
113
|
-
|
114
|
-
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RASN1
|
2
4
|
module Types
|
3
|
-
|
4
5
|
# @abstract This class SHOULD be used as base class for all ASN.1 primitive
|
5
6
|
# types.
|
6
7
|
# Base class for all ASN.1 constructed types
|
@@ -12,19 +13,16 @@ module RASN1
|
|
12
13
|
def inspect(level=0)
|
13
14
|
case @value
|
14
15
|
when Array
|
15
|
-
str =
|
16
|
-
str <<
|
17
|
-
|
18
|
-
level = level.abs
|
19
|
-
str << "#{type}:\n"
|
20
|
-
level += 1
|
16
|
+
str = common_inspect(level)
|
17
|
+
str << "\n"
|
18
|
+
level = level.abs + 1
|
21
19
|
@value.each do |item|
|
22
20
|
case item
|
23
21
|
when Base, Model
|
24
|
-
next if item.optional? and item.value.nil?
|
25
22
|
str << "#{item.inspect(level)}\n"
|
26
23
|
else
|
27
|
-
str <<
|
24
|
+
str << ' ' * level
|
25
|
+
str << "#{item.inspect}\n"
|
28
26
|
end
|
29
27
|
end
|
30
28
|
str
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RASN1
|
2
4
|
module Types
|
3
|
-
|
4
5
|
# ASN.1 Enumerated
|
5
6
|
#
|
6
7
|
# An enumerated type permits to assign names to integer values. It may be defined
|
@@ -21,23 +22,17 @@ module RASN1
|
|
21
22
|
# @!attribute enum
|
22
23
|
# @return [Hash]
|
23
24
|
|
24
|
-
|
25
|
+
# Enumerated id value
|
26
|
+
ID = 0x0a
|
25
27
|
|
26
|
-
# @
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
# @raise [EnumeratedError] +:default+ value is unknown
|
31
|
-
# @overload initialize(value, options={})
|
32
|
-
# @param [Object] value value to set for this ASN.1 object
|
33
|
-
# @option options [Hash] :enum enumeration hash. Keys are names, and values
|
34
|
-
# are integers. This key is mandatory.
|
35
|
-
# @raise [EnumeratedError] +:enum+ key is not present
|
36
|
-
# @raise [EnumeratedError] +:default+ value is unknown
|
28
|
+
# @option options [Hash] :enum enumeration hash. Keys are names, and values
|
29
|
+
# are integers. This key is mandatory.
|
30
|
+
# @raise [EnumeratedError] +:enum+ key is not present
|
31
|
+
# @raise [EnumeratedError] +:default+ value is unknown
|
37
32
|
# @see Base#initialize common options to all ASN.1 types
|
38
|
-
def initialize(
|
33
|
+
def initialize(options={})
|
39
34
|
super
|
40
|
-
raise EnumeratedError, 'no enumeration given' if @enum.
|
35
|
+
raise EnumeratedError, 'no enumeration given' if @enum.empty?
|
41
36
|
end
|
42
37
|
|
43
38
|
# @return [Hash]
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RASN1
|
2
4
|
module Types
|
3
|
-
|
4
5
|
# ASN.1 GeneralizedTime
|
5
6
|
#
|
6
7
|
# +{#value} of a {GeneralizedTime} should be a ruby Time.
|
@@ -20,7 +21,8 @@ module RASN1
|
|
20
21
|
# second are supported.
|
21
22
|
# @author Sylvain Daubert
|
22
23
|
class GeneralizedTime < Primitive
|
23
|
-
|
24
|
+
# GeneralizedTime id value
|
25
|
+
ID = 24
|
24
26
|
|
25
27
|
# Get ASN.1 type
|
26
28
|
# @return [String]
|
@@ -28,83 +30,122 @@ module RASN1
|
|
28
30
|
'GeneralizedTime'
|
29
31
|
end
|
30
32
|
|
33
|
+
# @return [DateTime]
|
34
|
+
def void_value
|
35
|
+
DateTime.now
|
36
|
+
end
|
37
|
+
|
31
38
|
private
|
32
|
-
|
39
|
+
|
33
40
|
def value_to_der
|
34
|
-
if @value.nsec
|
41
|
+
if @value.nsec.positive?
|
35
42
|
der = @value.getutc.strftime('%Y%m%d%H%M%S.%9NZ')
|
36
43
|
der.sub(/0+Z/, 'Z')
|
37
44
|
else
|
38
45
|
@value.getutc.strftime('%Y%m%d%H%M%SZ')
|
39
46
|
end
|
40
47
|
end
|
41
|
-
|
42
|
-
def der_to_value(der, ber: false)
|
48
|
+
|
49
|
+
def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
|
43
50
|
date_hour, fraction = der.split('.')
|
51
|
+
date_hour = date_hour.to_s
|
52
|
+
fraction = fraction.to_s
|
53
|
+
|
54
|
+
if fraction.empty?
|
55
|
+
value_when_fraction_empty(date_hour)
|
56
|
+
elsif fraction[-1] == 'Z'
|
57
|
+
value_when_fraction_ends_with_z(date_hour, fraction)
|
58
|
+
else
|
59
|
+
value_on_others_cases(date_hour, fraction)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def value_when_fraction_empty(date_hour)
|
44
64
|
utc_offset_forced = false
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
65
|
+
|
66
|
+
if (date_hour[-1] != 'Z') && (date_hour !~ /[+-]\d+$/)
|
67
|
+
# If not UTC, have to add offset with UTC to force
|
68
|
+
# DateTime#strptime to generate a local time. But this difference
|
69
|
+
# may be errored because of DST.
|
70
|
+
date_hour << Time.now.strftime('%z')
|
71
|
+
utc_offset_forced = true
|
72
|
+
end
|
73
|
+
|
74
|
+
value_from(date_hour)
|
75
|
+
fix_dst if utc_offset_forced
|
76
|
+
end
|
77
|
+
|
78
|
+
def value_when_fraction_ends_with_z(date_hour, fraction)
|
79
|
+
fraction = fraction[0...-1]
|
80
|
+
date_hour << 'Z'
|
81
|
+
frac_base = value_from(date_hour)
|
82
|
+
fix_value(fraction, frac_base)
|
83
|
+
end
|
84
|
+
|
85
|
+
def value_on_others_cases(date_hour, fraction)
|
86
|
+
match = fraction.match(/(\d+)([+-]\d+)/)
|
87
|
+
if match
|
88
|
+
# fraction contains fraction and timezone info. Split them
|
89
|
+
fraction = match[1]
|
90
|
+
date_hour << match[2]
|
53
91
|
else
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# fraction contains fraction and timezone info. Split them
|
61
|
-
fraction = match[1]
|
62
|
-
date_hour << match[2]
|
63
|
-
else
|
64
|
-
# fraction only contains fraction.
|
65
|
-
# Have to add offset with UTC to force DateTime#strptime to
|
66
|
-
# generate a local time. But this difference may be errored
|
67
|
-
# because of DST.
|
68
|
-
date_hour << Time.now.strftime('%z')
|
69
|
-
utc_offset_forced = true
|
70
|
-
end
|
71
|
-
end
|
92
|
+
# fraction only contains fraction.
|
93
|
+
# Have to add offset with UTC to force DateTime#strptime to
|
94
|
+
# generate a local time. But this difference may be errored
|
95
|
+
# because of DST.
|
96
|
+
date_hour << Time.now.strftime('%z')
|
97
|
+
utc_offset_forced = true
|
72
98
|
end
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
if date_hour[-1] == 'Z'
|
82
|
-
frac_base = 1
|
83
|
-
'%Y%m%d%H%M%SZ'
|
84
|
-
else
|
85
|
-
frac_base = 60 * 60
|
86
|
-
'%Y%m%d%H%z'
|
87
|
-
end
|
88
|
-
when 17
|
89
|
-
frac_base = 60
|
90
|
-
'%Y%m%d%H%M%z'
|
91
|
-
when 19
|
92
|
-
frac_base = 1
|
93
|
-
'%Y%m%d%H%M%S%z'
|
94
|
-
else
|
95
|
-
prefix = @name.nil? ? type : "tag #{@name}"
|
96
|
-
raise ASN1Error, "#{prefix}: unrecognized format: #{der}"
|
97
|
-
end
|
99
|
+
|
100
|
+
frac_base = value_from(date_hour)
|
101
|
+
fix_dst if utc_offset_forced
|
102
|
+
fix_value(fraction, frac_base)
|
103
|
+
end
|
104
|
+
|
105
|
+
def value_from(date_hour)
|
106
|
+
format, frac_base = strformat(date_hour)
|
98
107
|
@value = DateTime.strptime(date_hour, format).to_time
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
108
|
+
frac_base
|
109
|
+
end
|
110
|
+
|
111
|
+
# Check DST. There may be a shift of one hour...
|
112
|
+
def fix_dst
|
113
|
+
compare_time = Time.new(*@value.to_a[0..5].reverse)
|
114
|
+
@value = compare_time if compare_time.utc_offset != @value.utc_offset
|
115
|
+
end
|
116
|
+
|
117
|
+
def fix_value(fraction, frac_base)
|
118
|
+
@value += ".#{fraction}".to_r * frac_base unless fraction.nil?
|
119
|
+
end
|
120
|
+
|
121
|
+
def strformat(date_hour) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
122
|
+
case date_hour.size
|
123
|
+
when 11
|
124
|
+
frac_base = 60 * 60
|
125
|
+
format = '%Y%m%d%HZ'
|
126
|
+
when 13
|
127
|
+
frac_base = 60
|
128
|
+
format = '%Y%m%d%H%MZ'
|
129
|
+
when 15
|
130
|
+
if date_hour[-1] == 'Z'
|
131
|
+
frac_base = 1
|
132
|
+
format = '%Y%m%d%H%M%SZ'
|
133
|
+
else
|
134
|
+
frac_base = 60 * 60
|
135
|
+
format = '%Y%m%d%H%z'
|
105
136
|
end
|
137
|
+
when 17
|
138
|
+
frac_base = 60
|
139
|
+
format = '%Y%m%d%H%M%z'
|
140
|
+
when 19
|
141
|
+
frac_base = 1
|
142
|
+
format = '%Y%m%d%H%M%S%z'
|
143
|
+
else
|
144
|
+
prefix = @name.nil? ? type : "tag #{@name}"
|
145
|
+
raise ASN1Error, "#{prefix}: unrecognized format: #{der}"
|
106
146
|
end
|
107
|
-
|
147
|
+
|
148
|
+
[format, frac_base]
|
108
149
|
end
|
109
150
|
end
|
110
151
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RASN1
|
2
4
|
module Types
|
3
|
-
|
4
5
|
# ASN.1 IA5 String
|
5
6
|
# @author Sylvain Daubert
|
6
7
|
class IA5String < OctetString
|
7
|
-
|
8
|
+
# IA5String id value
|
9
|
+
ID = 22
|
8
10
|
|
9
11
|
# Get ASN.1 type
|
10
12
|
# @return [String]
|
@@ -13,15 +15,15 @@ module RASN1
|
|
13
15
|
end
|
14
16
|
|
15
17
|
private
|
16
|
-
|
18
|
+
|
17
19
|
def value_to_der
|
18
20
|
@value.to_s.force_encoding('US-ASCII').force_encoding('BINARY')
|
19
21
|
end
|
20
22
|
|
21
|
-
def der_to_value(der, ber:false)
|
23
|
+
def der_to_value(der, ber: false)
|
22
24
|
super
|
23
|
-
@value.force_encoding('US-ASCII')
|
25
|
+
@value.to_s.force_encoding('US-ASCII')
|
24
26
|
end
|
25
|
-
|
27
|
+
end
|
26
28
|
end
|
27
29
|
end
|