rasn1 0.13.0 → 0.13.1
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/LICENSE +1 -0
- data/README.md +1 -1
- data/lib/rasn1/model.rb +23 -14
- data/lib/rasn1/tracer.rb +5 -5
- data/lib/rasn1/types/any.rb +4 -3
- data/lib/rasn1/types/base.rb +3 -3
- data/lib/rasn1/types/constrained.rb +3 -15
- data/lib/rasn1/types/generalized_time.rb +11 -12
- data/lib/rasn1/types/integer.rb +11 -7
- data/lib/rasn1/types/object_id.rb +9 -6
- data/lib/rasn1/types/sequence_of.rb +1 -5
- data/lib/rasn1/types.rb +10 -8
- data/lib/rasn1/version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7f6fe2fadbdb5b72ec51995e911ac9adc7efbf497708ca581c2870ed3622b31
|
4
|
+
data.tar.gz: 6b68a59752a7ee439a7401b51415070b51ef3241f65864d263c1da9bfcdb2290
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d67a67c02d381d92ca93552834cdfc5bce175dc31794020c1d39b3fcea6301a50393f1c964c94d04ef7e14b5593275e5f72873bc89097118ce1abe0c6e4c582a
|
7
|
+
data.tar.gz: 5f2a8486a6ec2709ab3ecae6b664a4a731394ee5ada28f8c5908734aaf20b3e485eb6f4f0d74dc25d238191875732e02299eda3ad5d765dd870b39bf880c3e3a
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
[](https://badge.fury.io/rb/rasn1)
|
2
|
-
[](https://github.com/lemontree55/rasn1/actions?query=workflow%3Aci)
|
3
3
|
|
4
4
|
# Rasn1
|
5
5
|
|
data/lib/rasn1/model.rb
CHANGED
@@ -68,7 +68,7 @@ module RASN1
|
|
68
68
|
Elem = Struct.new(:name, :proc_or_class, :content) do
|
69
69
|
# @param [String,Symbol] name
|
70
70
|
# @param [Proc,Class] proc_or_class
|
71
|
-
# @param [
|
71
|
+
# @param [Array,nil] content
|
72
72
|
def initialize(name, proc_or_class, content)
|
73
73
|
if content.is_a?(Array)
|
74
74
|
duplicate_names = find_all_duplicate_names(content.map(&:name) + [name])
|
@@ -278,7 +278,7 @@ module RASN1
|
|
278
278
|
# @return [Elem]
|
279
279
|
# @see Types::SetOf#initialize
|
280
280
|
%w[sequence set].each do |type|
|
281
|
-
define_type_accel_of(type, Types.const_get("#{type.capitalize}Of"))
|
281
|
+
define_type_accel_of(type, Types.const_get(:"#{type.capitalize}Of"))
|
282
282
|
end
|
283
283
|
|
284
284
|
# @!method boolean(name, options)
|
@@ -461,6 +461,7 @@ module RASN1
|
|
461
461
|
root.value
|
462
462
|
else
|
463
463
|
elt = by_name(name)
|
464
|
+
return nil if elt.nil?
|
464
465
|
|
465
466
|
unless args.empty?
|
466
467
|
args.each do |arg|
|
@@ -504,14 +505,15 @@ module RASN1
|
|
504
505
|
|
505
506
|
# Give a (nested) element from its name
|
506
507
|
# @param [String, Symbol] name
|
507
|
-
# @return [Model, Types::Base]
|
508
|
+
# @return [Model, Types::Base, nil]
|
508
509
|
def by_name(name)
|
509
510
|
elt = self[name]
|
510
511
|
return elt unless elt.nil?
|
511
512
|
|
512
513
|
@elements.each_key do |subelt_name|
|
513
|
-
|
514
|
-
|
514
|
+
subelt = self[subelt_name]
|
515
|
+
if subelt.is_a?(Model)
|
516
|
+
elt = subelt[name]
|
515
517
|
return elt unless elt.nil?
|
516
518
|
end
|
517
519
|
end
|
@@ -541,7 +543,12 @@ module RASN1
|
|
541
543
|
class_element = self.class.class_eval { @root }
|
542
544
|
@root_name = class_element.name
|
543
545
|
@elements = {}
|
544
|
-
@elements[@root_name] =
|
546
|
+
@elements[@root_name] = case class_element
|
547
|
+
when WrapElem
|
548
|
+
generate_wrapper(class_element)
|
549
|
+
else
|
550
|
+
get_type(class_element.proc_or_class, self.class.options || {})
|
551
|
+
end
|
545
552
|
class_element
|
546
553
|
end
|
547
554
|
|
@@ -577,17 +584,18 @@ module RASN1
|
|
577
584
|
|
578
585
|
def initialize_elements(obj, args)
|
579
586
|
args.each do |name, value|
|
580
|
-
|
587
|
+
subobj = obj[name]
|
588
|
+
next unless subobj
|
581
589
|
|
582
590
|
case value
|
583
591
|
when Hash
|
584
|
-
raise ArgumentError, "element #{name}: may only pass a Hash for Model elements" unless
|
592
|
+
raise ArgumentError, "element #{name}: may only pass a Hash for Model elements" unless subobj.is_a?(Model)
|
585
593
|
|
586
|
-
initialize_elements
|
594
|
+
initialize_elements(subobj, value)
|
587
595
|
when Array
|
588
|
-
initialize_element_from_array(
|
596
|
+
initialize_element_from_array(subobj, value)
|
589
597
|
else
|
590
|
-
|
598
|
+
subobj.value = value
|
591
599
|
end
|
592
600
|
end
|
593
601
|
end
|
@@ -656,12 +664,13 @@ module RASN1
|
|
656
664
|
end
|
657
665
|
|
658
666
|
def wrapper_to_h(wrap)
|
659
|
-
|
667
|
+
el = wrap.element
|
668
|
+
case el
|
660
669
|
when Model
|
661
|
-
hsh =
|
670
|
+
hsh = el.to_h
|
662
671
|
hsh[hsh.keys.first]
|
663
672
|
else
|
664
|
-
private_to_h(
|
673
|
+
private_to_h(el)
|
665
674
|
end
|
666
675
|
end
|
667
676
|
end
|
data/lib/rasn1/tracer.rb
CHANGED
@@ -75,8 +75,8 @@ module RASN1
|
|
75
75
|
# @private
|
76
76
|
# Unpatch {#do_parse} to remove tracing ability
|
77
77
|
def stop_tracing
|
78
|
-
alias_method :do_parse, :do_parse_without_tracing
|
79
|
-
alias_method :do_parse_explicit, :do_parse_explicit_without_tracing
|
78
|
+
alias_method :do_parse, :do_parse_without_tracing
|
79
|
+
alias_method :do_parse_explicit, :do_parse_explicit_without_tracing
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
@@ -108,7 +108,7 @@ module RASN1
|
|
108
108
|
# @private
|
109
109
|
# Unpatch {#parse!} to remove tracing ability
|
110
110
|
def stop_tracing
|
111
|
-
alias_method :parse!, :parse_without_tracing
|
111
|
+
alias_method :parse!, :parse_without_tracing
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
@@ -133,7 +133,7 @@ module RASN1
|
|
133
133
|
# @private
|
134
134
|
# Unpatch {#der_to_value!} to remove tracing ability
|
135
135
|
def stop_tracing
|
136
|
-
alias_method :der_to_value, :der_to_value_without_tracing
|
136
|
+
alias_method :der_to_value, :der_to_value_without_tracing
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
@@ -158,7 +158,7 @@ module RASN1
|
|
158
158
|
# @private
|
159
159
|
# Unpatch {#der_to_value!} to remove tracing ability
|
160
160
|
def stop_tracing
|
161
|
-
alias_method :der_to_value, :der_to_value_without_tracing
|
161
|
+
alias_method :der_to_value, :der_to_value_without_tracing
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
data/lib/rasn1/types/any.rb
CHANGED
@@ -61,7 +61,7 @@ module RASN1
|
|
61
61
|
private
|
62
62
|
|
63
63
|
def common_inspect(level)
|
64
|
-
lvl =
|
64
|
+
lvl = [0, level].max
|
65
65
|
str = ' ' * lvl
|
66
66
|
str << "#{@name} " unless @name.nil?
|
67
67
|
str << asn1_class.to_s.upcase << ' ' unless asn1_class == :universal
|
@@ -82,9 +82,10 @@ module RASN1
|
|
82
82
|
total_length += id_size
|
83
83
|
|
84
84
|
@no_value = false
|
85
|
-
|
85
|
+
real_value = der[0, total_length].to_s
|
86
|
+
@value = real_value
|
86
87
|
|
87
|
-
[total_length,
|
88
|
+
[total_length, real_value]
|
88
89
|
end
|
89
90
|
|
90
91
|
def trace_any
|
data/lib/rasn1/types/base.rb
CHANGED
@@ -374,7 +374,7 @@ module RASN1
|
|
374
374
|
end
|
375
375
|
|
376
376
|
def common_inspect(level)
|
377
|
-
lvl = level
|
377
|
+
lvl = [level, 0].max
|
378
378
|
str = ' ' * lvl
|
379
379
|
str << "#{@name} " unless @name.nil?
|
380
380
|
str << asn1_class_to_s
|
@@ -427,7 +427,7 @@ module RASN1
|
|
427
427
|
when nil
|
428
428
|
@asn1_class = :universal
|
429
429
|
when Symbol
|
430
|
-
raise ClassError unless CLASSES.key?
|
430
|
+
raise ClassError unless CLASSES.key?(asn1_class)
|
431
431
|
|
432
432
|
@asn1_class = asn1_class
|
433
433
|
else
|
@@ -621,7 +621,7 @@ module RASN1
|
|
621
621
|
def find_type(id)
|
622
622
|
Types.constants.map { |c| Types.const_get(c) }
|
623
623
|
.select { |klass| klass < Primitive || klass < Constructed }
|
624
|
-
.find { |klass| klass::ID
|
624
|
+
.find { |klass| id == klass::ID }
|
625
625
|
end
|
626
626
|
|
627
627
|
def bin2hex(str)
|
@@ -9,12 +9,8 @@ module RASN1
|
|
9
9
|
module Constrained
|
10
10
|
# Define class/module methods for {Constrained} module
|
11
11
|
module ClassMethods
|
12
|
-
#
|
13
|
-
|
14
|
-
# @return [Proc,nil]
|
15
|
-
def constraint=(constraint)
|
16
|
-
@constraint = constraint
|
17
|
-
end
|
12
|
+
# @return [Proc] proc to check constraints
|
13
|
+
attr_accessor :constraint
|
18
14
|
|
19
15
|
# Check if a constraint is really defined
|
20
16
|
# @return [Boolean]
|
@@ -31,15 +27,7 @@ module RASN1
|
|
31
27
|
end
|
32
28
|
end
|
33
29
|
|
34
|
-
|
35
|
-
# @return [Proc] proc to check constraints
|
36
|
-
attr_reader :constraint
|
37
|
-
|
38
|
-
# Extend +base+ with {ClassMethods}
|
39
|
-
def included(base)
|
40
|
-
base.extend ClassMethods
|
41
|
-
end
|
42
|
-
end
|
30
|
+
extend ClassMethods
|
43
31
|
|
44
32
|
# Redefined +#value=+ to check constraint before assigning +val+
|
45
33
|
# @see Types::Base#value=
|
@@ -71,26 +71,25 @@ module RASN1
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def value_when_fraction_empty(date_hour)
|
74
|
+
# Ruby 3.0: special handle for timezone
|
75
|
+
# From 3.1: "Z" and "-0100" are supported
|
76
|
+
# Below 3.1: should be "-01:00" or "+00:00"
|
74
77
|
tz = if date_hour[-1] == 'Z'
|
75
78
|
date_hour.slice!(-1, 1)
|
76
79
|
'+00:00' # Ruby 3.0: to remove after end-of support of ruby 3.0
|
77
80
|
elsif date_hour.match?(/[+-]\d+$/)
|
78
81
|
# Ruby 3.0
|
79
82
|
# date_hour.slice!(-5, 5)
|
80
|
-
zone = date_hour.slice!(-5, 5)
|
81
|
-
zone[0, 3]
|
83
|
+
zone = date_hour.slice!(-5, 5).to_s
|
84
|
+
"#{zone[0, 3]}:#{zone[3, 2]}"
|
82
85
|
end
|
83
86
|
year = date_hour.slice!(0, 4).to_i
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
others << tz
|
91
|
-
end
|
92
|
-
@value = Time.new(year, *others)
|
93
|
-
# From 3.1: replace all this code by: Time.new(year, *others, in: tz)
|
87
|
+
month = date_hour.slice!(0, 2).to_i
|
88
|
+
day = date_hour.slice!(0, 2).to_i
|
89
|
+
hour = date_hour.slice!(0, 2).to_i
|
90
|
+
minute = date_hour.slice!(0, 2).to_i
|
91
|
+
second = date_hour.slice!(0, 2).to_i
|
92
|
+
@value = Time.new(year, month, day, hour, minute, second, tz)
|
94
93
|
end
|
95
94
|
|
96
95
|
def value_when_fraction_ends_with_z(date_hour, fraction)
|
data/lib/rasn1/types/integer.rb
CHANGED
@@ -45,10 +45,12 @@ module RASN1
|
|
45
45
|
# Integer value
|
46
46
|
# @return [Integer]
|
47
47
|
def to_i
|
48
|
-
|
49
|
-
|
48
|
+
val = value? ? @value : @default
|
49
|
+
case val
|
50
|
+
when String, Symbol
|
51
|
+
@enum[val]
|
50
52
|
else
|
51
|
-
|
53
|
+
val || 0
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
@@ -135,10 +137,12 @@ module RASN1
|
|
135
137
|
end
|
136
138
|
|
137
139
|
def der_to_value(der, ber: false)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
140
|
+
int_value = der_to_int_value(der, ber: ber)
|
141
|
+
@value = if @enum.empty?
|
142
|
+
int_value
|
143
|
+
else
|
144
|
+
int_to_enum(int_value)
|
145
|
+
end
|
142
146
|
end
|
143
147
|
|
144
148
|
def explicit_type
|
@@ -11,18 +11,21 @@ module RASN1
|
|
11
11
|
private
|
12
12
|
|
13
13
|
def value_to_der
|
14
|
-
ids = @value.to_s.split('.').map
|
14
|
+
ids = @value.to_s.split('.').map(&:to_i)
|
15
15
|
|
16
16
|
raise ASN1Error, "OBJECT ID #{@name}: first subidentifier should be less than 3" if ids[0] > 2
|
17
17
|
raise ASN1Error, "OBJECT ID #{@name}: second subidentifier should be less than 40" if (ids[0] < 2) && (ids[1] > 39)
|
18
18
|
|
19
19
|
ids[0, 2] = ids[0] * 40 + ids[1]
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
octets = []
|
21
|
+
ids.each do |v|
|
22
|
+
if v < 128
|
23
|
+
octets << v
|
24
|
+
else
|
25
|
+
octets.concat(unsigned_to_chained_octets(v))
|
26
|
+
end
|
24
27
|
end
|
25
|
-
|
28
|
+
octets.pack('C*')
|
26
29
|
end
|
27
30
|
|
28
31
|
def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
|
@@ -144,11 +144,7 @@ module RASN1
|
|
144
144
|
nb_bytes = 0
|
145
145
|
|
146
146
|
while nb_bytes < der.length
|
147
|
-
type =
|
148
|
-
@of_type.dup
|
149
|
-
else
|
150
|
-
of_type_class.new
|
151
|
-
end
|
147
|
+
type = of_type_class.new
|
152
148
|
nb_bytes += type.parse!(der[nb_bytes, der.length])
|
153
149
|
@value << type
|
154
150
|
end
|
data/lib/rasn1/types.rb
CHANGED
@@ -32,18 +32,20 @@ module RASN1
|
|
32
32
|
# ID and size of identifier octets
|
33
33
|
def self.decode_identifier_octets(der)
|
34
34
|
first_octet = der.unpack1('C').to_i
|
35
|
-
asn1_class = Types::Base::CLASSES.key(first_octet & Types::Base::CLASS_MASK)
|
35
|
+
asn1_class = Types::Base::CLASSES.key(first_octet & Types::Base::CLASS_MASK) || :universal
|
36
36
|
pc = (first_octet & Types::Constructed::ASN1_PC).positive? ? :constructed : :primitive
|
37
37
|
id = first_octet & Types::Base::MULTI_OCTETS_ID
|
38
38
|
|
39
39
|
size = if id == Types::Base::MULTI_OCTETS_ID
|
40
40
|
id = 0
|
41
|
-
|
42
|
-
|
41
|
+
count = 1
|
42
|
+
der[1..-1].to_s.bytes.each do |octet|
|
43
|
+
count += 1
|
43
44
|
|
44
45
|
id = (id << 7) | (octet & 0x7f)
|
45
|
-
break
|
46
|
+
break if (octet & 0x80).zero?
|
46
47
|
end
|
48
|
+
count
|
47
49
|
else
|
48
50
|
1
|
49
51
|
end
|
@@ -98,11 +100,11 @@ module RASN1
|
|
98
100
|
# (value >= 0) && (value < 2**32)
|
99
101
|
# end
|
100
102
|
def self.define_type(name, from:, in_module: self, &block)
|
101
|
-
constraint = block
|
103
|
+
constraint = block&.to_proc
|
102
104
|
|
103
|
-
new_klass = Class.new(from)
|
104
|
-
|
105
|
-
|
105
|
+
new_klass = Class.new(from)
|
106
|
+
new_klass.include(Constrained)
|
107
|
+
new_klass.extend(Constrained::ClassMethods)
|
106
108
|
new_klass.constraint = constraint
|
107
109
|
|
108
110
|
in_module.const_set(name, new_klass)
|
data/lib/rasn1/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rasn1
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.13.
|
4
|
+
version: 0.13.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- LemonTree55
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: strptime
|
@@ -28,7 +28,7 @@ description: |
|
|
28
28
|
RASN1 is a pure ruby ASN.1 library. It may encode and decode DER and BER
|
29
29
|
encodings.
|
30
30
|
email:
|
31
|
-
-
|
31
|
+
- lenontree@proton.me
|
32
32
|
executables: []
|
33
33
|
extensions: []
|
34
34
|
extra_rdoc_files:
|
@@ -70,13 +70,13 @@ files:
|
|
70
70
|
- lib/rasn1/types/visible_string.rb
|
71
71
|
- lib/rasn1/version.rb
|
72
72
|
- lib/rasn1/wrapper.rb
|
73
|
-
homepage: https://github.com/
|
73
|
+
homepage: https://github.com/lemontree55/rasn1
|
74
74
|
licenses:
|
75
75
|
- MIT
|
76
76
|
metadata:
|
77
|
-
homepage_uri: https://github.com/
|
78
|
-
source_code_uri: https://github.com/
|
79
|
-
bug_tracker_uri: https://github.com/
|
77
|
+
homepage_uri: https://github.com/lemontree55/rasn1
|
78
|
+
source_code_uri: https://github.com/lemontree55/rasn1
|
79
|
+
bug_tracker_uri: https://github.com/lemontree55/rasn1/issues
|
80
80
|
documentation_uri: https://www.rubydoc.info/gems/rasn1
|
81
81
|
post_install_message:
|
82
82
|
rdoc_options:
|