rasn1 0.13.0 → 0.13.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/rasn1.svg)](https://badge.fury.io/rb/rasn1)
|
2
|
-
[![Action status](https://github.com/
|
2
|
+
[![Action status](https://github.com/lemontree55/rasn1/workflows/ci/badge.svg?branch=master)](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:
|