rasn1 0.16.3 → 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/model/accel.rb +229 -0
- data/lib/rasn1/model.rb +30 -151
- data/lib/rasn1/tracer.rb +9 -9
- data/lib/rasn1/types/generalized_time.rb +1 -9
- data/lib/rasn1/version.rb +1 -1
- data/lib/rasn1.rb +4 -4
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 67e24db40c3ec0a8e7d7ad23211549c1aadda9511ea73f632034a4cdefa97ae0
|
|
4
|
+
data.tar.gz: d8847b0b52cce0014f02772077da519df146c14a1f65ffebc72cc206e888b0cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 12da7b29112a40073dd64e3eb949412cd941932d63fb87e2cf36cf020c1df784cdd85e6e2cd04113f8bf74e7b16c630fad2346b885933874f86dcd329f42511b
|
|
7
|
+
data.tar.gz: a5294cfc1a3ebc0430c1be31558ed1e33ac97e5d87ad8ff3c14d6c8633b251d53b33e7818762f46bb6272c4f71da439a42aa86f79413c3af405b5b3d076777a3
|
data/README.md
CHANGED
|
@@ -52,7 +52,9 @@ ComplexRecord ::= SEQUENCE {
|
|
|
52
52
|
}
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
### Create
|
|
55
|
+
### Create an ASN.1 model
|
|
56
|
+
|
|
57
|
+
A model is created this way:
|
|
56
58
|
|
|
57
59
|
```ruby
|
|
58
60
|
class Record < RASN1::Model
|
|
@@ -63,14 +65,31 @@ class Record < RASN1::Model
|
|
|
63
65
|
end
|
|
64
66
|
```
|
|
65
67
|
|
|
68
|
+
or, this ways in a more rubyish style:
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
# This Record class is defined as a sequence conaining:
|
|
72
|
+
# * an ID (integer)
|
|
73
|
+
# * a room number (integer, with explicit tag, optional)
|
|
74
|
+
# * a house if (integer, with explicit tag and a default value)
|
|
75
|
+
class Record < RASN1::Model
|
|
76
|
+
sequence :record do
|
|
77
|
+
integer(:id)
|
|
78
|
+
integer(:room, implicit: 0, optional: true)
|
|
79
|
+
integer(:house, implicit: 1, default: 0)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
```
|
|
83
|
+
|
|
66
84
|
More comple classes may be designed by nesting simple classes. For example:
|
|
67
85
|
|
|
68
86
|
```ruby
|
|
69
87
|
class ComplexRecord < RASN1::Model
|
|
70
|
-
sequence :cplx_record
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
88
|
+
sequence :cplx_record do
|
|
89
|
+
boolean(:bool)
|
|
90
|
+
octet_string(:data, explicit: 0)
|
|
91
|
+
model(:a_record, Record) # Use another model in model
|
|
92
|
+
end
|
|
74
93
|
end
|
|
75
94
|
```
|
|
76
95
|
|
|
@@ -115,10 +134,6 @@ record.set id: 124, house: 155
|
|
|
115
134
|
record.to_der # => String
|
|
116
135
|
```
|
|
117
136
|
|
|
118
|
-
### More information
|
|
119
|
-
|
|
120
|
-
see <https://github.com/sdaubert/rasn1/wiki>
|
|
121
|
-
|
|
122
137
|
## Contributing
|
|
123
138
|
|
|
124
|
-
Bug reports and pull requests are welcome on GitHub at <https://
|
|
139
|
+
Bug reports and pull requests are welcome on GitHub at <https://codeberg.org/lemontree55/rasn1>.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is part of RASN1
|
|
4
|
+
# See https://codeberg.org/lemontree55/rasn1 for more informations
|
|
5
|
+
# Copyright (C) 2016-2024 Sylvain Daubert <sylvain.daubert@laposte.net>
|
|
6
|
+
# Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
|
|
7
|
+
# This program is published under MIT license.
|
|
8
|
+
|
|
9
|
+
module RASN1
|
|
10
|
+
class Model
|
|
11
|
+
# Define helper methods to define models
|
|
12
|
+
# @author Sylvain Daubert
|
|
13
|
+
module Accel
|
|
14
|
+
# @return [Hash]
|
|
15
|
+
attr_reader :options
|
|
16
|
+
|
|
17
|
+
# On inheritance, create +@elements+ class variable
|
|
18
|
+
# @param klass [Class]
|
|
19
|
+
# @return [void]
|
|
20
|
+
def inherited(klass)
|
|
21
|
+
super
|
|
22
|
+
current_elements = @elements
|
|
23
|
+
klass.class_eval { @elements = current_elements.dup }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @since 0.17.0
|
|
27
|
+
def elements
|
|
28
|
+
return @elements unless @elements.nil?
|
|
29
|
+
|
|
30
|
+
@elements = []
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Use another model in this model
|
|
34
|
+
# @param name [String,Symbol]
|
|
35
|
+
# @param model_klass [Class]
|
|
36
|
+
# @return [Elem]
|
|
37
|
+
def model(name, model_klass)
|
|
38
|
+
push_element(ModelElem.new(name, model_klass))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @since 0.17.0
|
|
42
|
+
# @param [BaseElem, WrapElem, ModelElem] elem
|
|
43
|
+
# @return [BaseElem, WrapElem, ModelElem] elem
|
|
44
|
+
def push_element(elem)
|
|
45
|
+
elements << elem
|
|
46
|
+
elem
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @since 0.17.0
|
|
50
|
+
def root
|
|
51
|
+
elements.last
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @since 0.17.0
|
|
55
|
+
def root=(elem)
|
|
56
|
+
if elements.empty?
|
|
57
|
+
elements << elem
|
|
58
|
+
else
|
|
59
|
+
elements[-1] = elem
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @overload wrapper(element, options={})
|
|
64
|
+
# Use a {Wrapper} around a {Types::Base} or a {Model} object
|
|
65
|
+
# @param element [Types::Base,Model]
|
|
66
|
+
# @param options [Hash]
|
|
67
|
+
# @return [WrapElem]
|
|
68
|
+
# @since 0.12
|
|
69
|
+
# @overload(options={})
|
|
70
|
+
# @param options [Hash]
|
|
71
|
+
# @return [WrapElem]
|
|
72
|
+
# @yieldreturn [BaseElem, ModelElem] element to wrapp
|
|
73
|
+
# @since 0.17.0
|
|
74
|
+
def wrapper(element_or_options={}, options={}, &)
|
|
75
|
+
case element_or_options
|
|
76
|
+
when Hash
|
|
77
|
+
element = generate_content(&).last
|
|
78
|
+
options = element_or_options
|
|
79
|
+
else
|
|
80
|
+
element = element_or_options
|
|
81
|
+
end
|
|
82
|
+
push_element(WrapElem.new(element, options))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Update options of root element.
|
|
86
|
+
# May be used when subclassing.
|
|
87
|
+
# class Model1 < RASN1::Model
|
|
88
|
+
# sequence :seq, implicit: 0,
|
|
89
|
+
# content: [bool(:bool), integer(:int)]
|
|
90
|
+
# end
|
|
91
|
+
#
|
|
92
|
+
# # same as Model1 but with implicit tag set to 1
|
|
93
|
+
# class Model2 < Model1
|
|
94
|
+
# root_options implicit: 1
|
|
95
|
+
# end
|
|
96
|
+
# @param options [Hash]
|
|
97
|
+
# @return [void]
|
|
98
|
+
# @since 0.12.0 may change name through +:name+
|
|
99
|
+
def root_options(options)
|
|
100
|
+
@options = options
|
|
101
|
+
return unless options.key?(:name)
|
|
102
|
+
|
|
103
|
+
self.root = root.dup
|
|
104
|
+
root.name = options[:name]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# @private
|
|
108
|
+
# @param accel_name [String,Symbol]
|
|
109
|
+
# @param klass [Class]
|
|
110
|
+
# @since 0.11.0
|
|
111
|
+
# @since 0.12.0 track source location on error (adfoster-r7)
|
|
112
|
+
def define_type_accel_base(accel_name, klass)
|
|
113
|
+
singleton_class.class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
|
114
|
+
def #{accel_name}(name, options={}) # def sequence(name, type, options)
|
|
115
|
+
options[:name] = name
|
|
116
|
+
proc = proc do |opts|
|
|
117
|
+
#{klass}.new(options.merge(opts)) # Sequence.new(options.merge(opts))
|
|
118
|
+
end
|
|
119
|
+
push_element(BaseElem.new(name, proc, nil))
|
|
120
|
+
end
|
|
121
|
+
EVAL
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# @private
|
|
125
|
+
# @param accel_name [String,Symbol]
|
|
126
|
+
# @param klass [Class]
|
|
127
|
+
# @since 0.17.0
|
|
128
|
+
def define_type_accel_container(accel_name, klass)
|
|
129
|
+
singleton_class.class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
|
130
|
+
def #{accel_name}(name, options={}, &block) # def sequence(name, type, options, &block)
|
|
131
|
+
options[:name] = name
|
|
132
|
+
proc = proc do |opts|
|
|
133
|
+
#{klass}.new(options.merge(opts)) # Sequence.new(options.merge(opts))
|
|
134
|
+
end
|
|
135
|
+
options[:content] ||= []
|
|
136
|
+
options[:content] += generate_content(&block)
|
|
137
|
+
push_element(BaseElem.new(name, proc, options[:content]))
|
|
138
|
+
end
|
|
139
|
+
EVAL
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# @private
|
|
143
|
+
# @since 0.17.0
|
|
144
|
+
def generate_content
|
|
145
|
+
return [] unless block_given?
|
|
146
|
+
|
|
147
|
+
previous_elements = @elements
|
|
148
|
+
@elements = []
|
|
149
|
+
yield
|
|
150
|
+
content = @elements
|
|
151
|
+
@elements = previous_elements
|
|
152
|
+
content
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# @private
|
|
156
|
+
# @param accel_name [String,Symbol]
|
|
157
|
+
# @param klass [Class]
|
|
158
|
+
# @since 0.11.0
|
|
159
|
+
# @since 0.12.0 track source location on error (adfoster-r7)
|
|
160
|
+
def define_type_accel_of(accel_name, klass)
|
|
161
|
+
singleton_class.class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
|
162
|
+
def #{accel_name}_of(name, type, options={}) # def sequence_of(name, type, options)
|
|
163
|
+
options[:name] = name
|
|
164
|
+
proc = proc do |opts|
|
|
165
|
+
#{klass}.new(type, options.merge(opts)) # SequenceOf.new(type, options.merge(opts))
|
|
166
|
+
end
|
|
167
|
+
push_element(BaseElem.new(name, proc, nil))
|
|
168
|
+
end
|
|
169
|
+
EVAL
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Define an accelarator to access a type in a model definition
|
|
173
|
+
# @param accel_name [String]
|
|
174
|
+
# @param klass [Class] class to instanciate
|
|
175
|
+
# @since 0.11.0
|
|
176
|
+
# @since 0.12.0 track source location on error (adfoster-r7)
|
|
177
|
+
def define_type_accel(accel_name, klass)
|
|
178
|
+
if klass <= Types::SequenceOf
|
|
179
|
+
define_type_accel_of(accel_name, klass)
|
|
180
|
+
elsif (klass <= Types::Sequence) || (klass <= Types::Choice)
|
|
181
|
+
define_type_accel_container(accel_name, klass)
|
|
182
|
+
else
|
|
183
|
+
define_type_accel_base(accel_name, klass)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# @param name [Symbol,String] name of object in model
|
|
188
|
+
# @param options [Hash]
|
|
189
|
+
# @return [Elem]
|
|
190
|
+
# @note This method is named +objectid+ and not +object_id+ to not override
|
|
191
|
+
# +Object#object_id+.
|
|
192
|
+
# @see Types::ObjectId#initialize
|
|
193
|
+
def objectid(name, options={})
|
|
194
|
+
options[:name] = name
|
|
195
|
+
proc = proc { |opts| Types::ObjectId.new(options.merge(opts)) }
|
|
196
|
+
push_element(BaseElem.new(name, proc, nil))
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# @param name [Symbol,String] name of object in model
|
|
200
|
+
# @param options [Hash]
|
|
201
|
+
# @return [Elem]
|
|
202
|
+
# @see Types::Any#initialize
|
|
203
|
+
def any(name, options={})
|
|
204
|
+
options[:name] = name
|
|
205
|
+
proc = proc { |opts| Types::Any.new(options.merge(opts)) }
|
|
206
|
+
push_element(BaseElem.new(name, proc, nil))
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Give type name (aka class name)
|
|
210
|
+
# @return [String]
|
|
211
|
+
def type
|
|
212
|
+
return @type if defined? @type
|
|
213
|
+
|
|
214
|
+
@type = self.to_s.gsub(/.*::/, '')
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Parse a DER/BER encoded string
|
|
218
|
+
# @param str [String]
|
|
219
|
+
# @param ber [Boolean] accept BER encoding or not
|
|
220
|
+
# @return [Model]
|
|
221
|
+
# @raise [ASN1Error] error on parsing
|
|
222
|
+
def parse(str, ber: false)
|
|
223
|
+
model = new
|
|
224
|
+
model.parse!(str, ber: ber)
|
|
225
|
+
model
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
data/lib/rasn1/model.rb
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
# Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
|
|
7
7
|
# This program is published under MIT license.
|
|
8
8
|
|
|
9
|
+
require_relative 'model/accel'
|
|
10
|
+
|
|
9
11
|
module RASN1
|
|
10
12
|
# @abstract
|
|
11
13
|
# {Model} class is a base class to define ASN.1 models.
|
|
@@ -16,7 +18,8 @@ module RASN1
|
|
|
16
18
|
# room [0] IMPLICIT INTEGER OPTIONAL,
|
|
17
19
|
# house [1] EXPLICIT INTEGER DEFAULT 0
|
|
18
20
|
# }
|
|
19
|
-
#
|
|
21
|
+
#
|
|
22
|
+
# You may create your model like this:
|
|
20
23
|
# class Record < RASN1::Model
|
|
21
24
|
# sequence(:record,
|
|
22
25
|
# content: [integer(:id),
|
|
@@ -24,6 +27,15 @@ module RASN1
|
|
|
24
27
|
# integer(:house, explicit: 1, default: 0)])
|
|
25
28
|
# end
|
|
26
29
|
#
|
|
30
|
+
# You may also use block style definition:
|
|
31
|
+
# class Record < RASN1::Model
|
|
32
|
+
# sequence :record do
|
|
33
|
+
# integer :id
|
|
34
|
+
# integer :room, implicit: 0, optional: true
|
|
35
|
+
# integer :house, explicit: 1, default: 0
|
|
36
|
+
# end
|
|
37
|
+
# end
|
|
38
|
+
#
|
|
27
39
|
# In a model, each element must have a unique name.
|
|
28
40
|
#
|
|
29
41
|
# === Parse a DER-encoded string
|
|
@@ -47,10 +59,12 @@ module RASN1
|
|
|
47
59
|
# == Create a more complex model
|
|
48
60
|
# Models may be nested. For example:
|
|
49
61
|
# class Record2 < RASN1::Model
|
|
50
|
-
# sequence
|
|
51
|
-
#
|
|
52
|
-
#
|
|
62
|
+
# sequence :record2 do
|
|
63
|
+
# boolean :rented, default: false)
|
|
64
|
+
# model :a_record, Record
|
|
65
|
+
# end
|
|
53
66
|
# end
|
|
67
|
+
#
|
|
54
68
|
# Set values like this:
|
|
55
69
|
# record2 = Record2.new
|
|
56
70
|
# record2[:rented] = true
|
|
@@ -67,15 +81,22 @@ module RASN1
|
|
|
67
81
|
# this method.
|
|
68
82
|
# @author Sylvain Daubert
|
|
69
83
|
# @author adfoster-r7 ModelValidationError, track source location for dynamic class methods
|
|
84
|
+
# @since 0.17 block notation
|
|
70
85
|
class Model # rubocop:disable Metrics/ClassLength
|
|
71
86
|
# @private Base Element
|
|
72
|
-
BaseElem
|
|
87
|
+
class BaseElem
|
|
88
|
+
attr_accessor :name
|
|
89
|
+
attr_reader :proc, :content, :block
|
|
90
|
+
|
|
73
91
|
# @param name [String,Symbol]
|
|
74
92
|
# @param proc [Proc]
|
|
75
93
|
# @param content [Array,nil]
|
|
76
|
-
def initialize(name, proc, content)
|
|
94
|
+
def initialize(name, proc, content, &block)
|
|
95
|
+
@name = name
|
|
96
|
+
@proc = proc
|
|
97
|
+
@content = content
|
|
98
|
+
@block = block
|
|
77
99
|
check_duplicates(content.map(&:name) + [name]) unless content.nil?
|
|
78
|
-
super
|
|
79
100
|
end
|
|
80
101
|
|
|
81
102
|
private
|
|
@@ -111,148 +132,6 @@ module RASN1
|
|
|
111
132
|
# @private Sequence types
|
|
112
133
|
SEQUENCE_TYPES = [Types::Sequence, Types::SequenceOf, Types::Set, Types::SetOf].freeze
|
|
113
134
|
|
|
114
|
-
# Define helper methods to define models
|
|
115
|
-
module Accel
|
|
116
|
-
# @return [Hash]
|
|
117
|
-
attr_reader :options
|
|
118
|
-
|
|
119
|
-
# Use another model in this model
|
|
120
|
-
# @param name [String,Symbol]
|
|
121
|
-
# @param model_klass [Class]
|
|
122
|
-
# @return [Elem]
|
|
123
|
-
def model(name, model_klass)
|
|
124
|
-
@root = ModelElem.new(name, model_klass)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# Use a {Wrapper} around a {Types::Base} or a {Model} object
|
|
128
|
-
# @param element [Types::Base,Model]
|
|
129
|
-
# @param options [Hash]
|
|
130
|
-
# @return [WrapElem]
|
|
131
|
-
# @since 0.12
|
|
132
|
-
def wrapper(element, options={})
|
|
133
|
-
@root = WrapElem.new(element, options)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
# Update options of root element.
|
|
137
|
-
# May be used when subclassing.
|
|
138
|
-
# class Model1 < RASN1::Model
|
|
139
|
-
# sequence :seq, implicit: 0,
|
|
140
|
-
# content: [bool(:bool), integer(:int)]
|
|
141
|
-
# end
|
|
142
|
-
#
|
|
143
|
-
# # same as Model1 but with implicit tag set to 1
|
|
144
|
-
# class Model2 < Model1
|
|
145
|
-
# root_options implicit: 1
|
|
146
|
-
# end
|
|
147
|
-
# @param options [Hash]
|
|
148
|
-
# @return [void]
|
|
149
|
-
# @since 0.12.0 may change name through +:name+
|
|
150
|
-
def root_options(options)
|
|
151
|
-
@options = options
|
|
152
|
-
return unless options.key?(:name)
|
|
153
|
-
|
|
154
|
-
@root = @root.dup
|
|
155
|
-
@root.name = options[:name]
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# On inheritance, create +@root+ class variable
|
|
159
|
-
# @param klass [Class]
|
|
160
|
-
# @return [void]
|
|
161
|
-
def inherited(klass)
|
|
162
|
-
super
|
|
163
|
-
root = @root
|
|
164
|
-
klass.class_eval { @root = root }
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
# @private
|
|
168
|
-
# @param accel_name [String,Symbol]
|
|
169
|
-
# @param klass [Class]
|
|
170
|
-
# @since 0.11.0
|
|
171
|
-
# @since 0.12.0 track source location on error (adfoster-r7)
|
|
172
|
-
def define_type_accel_base(accel_name, klass)
|
|
173
|
-
singleton_class.class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
|
174
|
-
def #{accel_name}(name, options={}) # def sequence(name, type, options)
|
|
175
|
-
options[:name] = name
|
|
176
|
-
proc = proc do |opts|
|
|
177
|
-
#{klass}.new(options.merge(opts)) # Sequence.new(options.merge(opts))
|
|
178
|
-
end
|
|
179
|
-
@root = BaseElem.new(name, proc, options[:content])
|
|
180
|
-
end
|
|
181
|
-
EVAL
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
# @private
|
|
185
|
-
# @param accel_name [String,Symbol]
|
|
186
|
-
# @param klass [Class]
|
|
187
|
-
# @since 0.11.0
|
|
188
|
-
# @since 0.12.0 track source location on error (adfoster-r7)
|
|
189
|
-
def define_type_accel_of(accel_name, klass)
|
|
190
|
-
singleton_class.class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
|
191
|
-
def #{accel_name}_of(name, type, options={}) # def sequence_of(name, type, options)
|
|
192
|
-
options[:name] = name
|
|
193
|
-
proc = proc do |opts|
|
|
194
|
-
#{klass}.new(type, options.merge(opts)) # SequenceOf.new(type, options.merge(opts))
|
|
195
|
-
end
|
|
196
|
-
@root = BaseElem.new(name, proc, nil)
|
|
197
|
-
end
|
|
198
|
-
EVAL
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
# Define an accelarator to access a type in a model definition
|
|
202
|
-
# @param accel_name [String]
|
|
203
|
-
# @param klass [Class] class to instanciate
|
|
204
|
-
# @since 0.11.0
|
|
205
|
-
# @since 0.12.0 track source location on error (adfoster-r7)
|
|
206
|
-
def define_type_accel(accel_name, klass)
|
|
207
|
-
if klass < Types::SequenceOf
|
|
208
|
-
define_type_accel_of(accel_name, klass)
|
|
209
|
-
else
|
|
210
|
-
define_type_accel_base(accel_name, klass)
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
# @param name [Symbol,String] name of object in model
|
|
215
|
-
# @param options [Hash]
|
|
216
|
-
# @return [Elem]
|
|
217
|
-
# @note This method is named +objectid+ and not +object_id+ to not override
|
|
218
|
-
# +Object#object_id+.
|
|
219
|
-
# @see Types::ObjectId#initialize
|
|
220
|
-
def objectid(name, options={})
|
|
221
|
-
options[:name] = name
|
|
222
|
-
proc = proc { |opts| Types::ObjectId.new(options.merge(opts)) }
|
|
223
|
-
@root = BaseElem.new(name, proc, nil)
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
# @param name [Symbol,String] name of object in model
|
|
227
|
-
# @param options [Hash]
|
|
228
|
-
# @return [Elem]
|
|
229
|
-
# @see Types::Any#initialize
|
|
230
|
-
def any(name, options={})
|
|
231
|
-
options[:name] = name
|
|
232
|
-
proc = proc { |opts| Types::Any.new(options.merge(opts)) }
|
|
233
|
-
@root = BaseElem.new(name, proc, nil)
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
# Give type name (aka class name)
|
|
237
|
-
# @return [String]
|
|
238
|
-
def type
|
|
239
|
-
return @type if defined? @type
|
|
240
|
-
|
|
241
|
-
@type = self.to_s.gsub(/.*::/, '')
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
# Parse a DER/BER encoded string
|
|
245
|
-
# @param str [String]
|
|
246
|
-
# @param ber [Boolean] accept BER encoding or not
|
|
247
|
-
# @return [Model]
|
|
248
|
-
# @raise [ASN1Error] error on parsing
|
|
249
|
-
def parse(str, ber: false)
|
|
250
|
-
model = new
|
|
251
|
-
model.parse!(str, ber: ber)
|
|
252
|
-
model
|
|
253
|
-
end
|
|
254
|
-
end
|
|
255
|
-
|
|
256
135
|
extend Accel
|
|
257
136
|
|
|
258
137
|
# @!method sequence(name, options)
|
|
@@ -274,7 +153,7 @@ module RASN1
|
|
|
274
153
|
# @return [Elem]
|
|
275
154
|
# @see Types::Choice#initialize
|
|
276
155
|
%w[sequence set choice].each do |type|
|
|
277
|
-
self.
|
|
156
|
+
self.define_type_accel_container(type, Types.const_get(type.capitalize))
|
|
278
157
|
end
|
|
279
158
|
|
|
280
159
|
# @!method sequence_of(name, type, options)
|
|
@@ -610,7 +489,7 @@ module RASN1
|
|
|
610
489
|
# @return [void]
|
|
611
490
|
def generate_root(args)
|
|
612
491
|
opts = args.slice(:name, :explicit, :implicit, :optional, :class, :default, :constructed, :tag_value)
|
|
613
|
-
root = self.class.
|
|
492
|
+
root = self.class.root
|
|
614
493
|
root_options = self.class.options || {}
|
|
615
494
|
root_options.merge!(opts)
|
|
616
495
|
@root_name = args[:name] || root.name
|
data/lib/rasn1/tracer.rb
CHANGED
|
@@ -38,6 +38,12 @@ module RASN1
|
|
|
38
38
|
level ||= @tracing_level
|
|
39
39
|
' ' * level
|
|
40
40
|
end
|
|
41
|
+
|
|
42
|
+
def higher_tracing_level
|
|
43
|
+
self.tracing_level += 1
|
|
44
|
+
yield
|
|
45
|
+
self.tracing_level -= 1
|
|
46
|
+
end
|
|
41
47
|
end
|
|
42
48
|
|
|
43
49
|
# Trace RASN1 parsing to +io+.
|
|
@@ -107,9 +113,7 @@ module RASN1
|
|
|
107
113
|
# @return [void]
|
|
108
114
|
# @see #parse!
|
|
109
115
|
def do_parse_explicit_with_tracing(data)
|
|
110
|
-
RASN1.tracer.
|
|
111
|
-
do_parse_explicit_without_tracing(data)
|
|
112
|
-
RASN1.tracer.tracing_level -= 1
|
|
116
|
+
RASN1.tracer.higher_tracing_level { do_parse_explicit_without_tracing(data) }
|
|
113
117
|
end
|
|
114
118
|
end
|
|
115
119
|
|
|
@@ -163,9 +167,7 @@ module RASN1
|
|
|
163
167
|
# der_to_value +der+ with tracing abillity
|
|
164
168
|
# @!macro do_parse
|
|
165
169
|
def der_to_value_with_tracing(der, ber: false)
|
|
166
|
-
RASN1.tracer.
|
|
167
|
-
der_to_value_without_tracing(der, ber: ber)
|
|
168
|
-
RASN1.tracer.tracing_level -= 1
|
|
170
|
+
RASN1.tracer.higher_tracing_level { der_to_value_without_tracing(der, ber: ber) }
|
|
169
171
|
end
|
|
170
172
|
end
|
|
171
173
|
|
|
@@ -191,9 +193,7 @@ module RASN1
|
|
|
191
193
|
# der_to_value +der+ with tracing abillity
|
|
192
194
|
# @!macro do_parse
|
|
193
195
|
def der_to_value_with_tracing(der, ber: false)
|
|
194
|
-
RASN1.tracer.
|
|
195
|
-
der_to_value_without_tracing(der, ber: ber)
|
|
196
|
-
RASN1.tracer.tracing_level -= 1
|
|
196
|
+
RASN1.tracer.higher_tracing_level { der_to_value_without_tracing(der, ber: ber) }
|
|
197
197
|
end
|
|
198
198
|
end
|
|
199
199
|
end
|
|
@@ -101,19 +101,11 @@ module RASN1
|
|
|
101
101
|
# Compute TZ from +date_hour+ string
|
|
102
102
|
# @param date_hour [String]
|
|
103
103
|
# @return [String]
|
|
104
|
-
# @note
|
|
105
|
-
# Ruby 3.0: special handle for timezone
|
|
106
|
-
# * From 3.1: "Z" and "-0100" are supported
|
|
107
|
-
# * Below 3.1: should be "-01:00" or "+00:00"
|
|
108
104
|
def compute_tz(date_hour)
|
|
109
105
|
if date_hour.end_with?('Z')
|
|
110
106
|
date_hour.slice!(-1, 1)
|
|
111
|
-
'+00:00' # Ruby 3.0: to remove after end-of support of ruby 3.0
|
|
112
107
|
elsif date_hour.match?(/[+-]\d+$/)
|
|
113
|
-
|
|
114
|
-
# date_hour.slice!(-5, 5)
|
|
115
|
-
zone = date_hour.slice!(-5, 5).to_s
|
|
116
|
-
"#{zone[0, 3]}:#{zone[3, 2]}"
|
|
108
|
+
date_hour.slice!(-5, 5)
|
|
117
109
|
end
|
|
118
110
|
end
|
|
119
111
|
|
data/lib/rasn1/version.rb
CHANGED
data/lib/rasn1.rb
CHANGED
|
@@ -41,16 +41,16 @@ module RASN1
|
|
|
41
41
|
size = type.parse!(der, ber: ber)
|
|
42
42
|
|
|
43
43
|
if CONTAINER_CLASSES.include?(type.class)
|
|
44
|
-
RASN1.tracer
|
|
44
|
+
RASN1.tracer&.tracing_level += 1
|
|
45
45
|
content = self.parse(type.value)
|
|
46
|
-
type.value = content
|
|
47
|
-
RASN1.tracer
|
|
46
|
+
type.value = Array(content)
|
|
47
|
+
RASN1.tracer&.tracing_level -= 1
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
result << type
|
|
51
51
|
der = der[size..]
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
result.size == 1 ? result
|
|
54
|
+
result.size == 1 ? result.first : result
|
|
55
55
|
end
|
|
56
56
|
end
|
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.
|
|
4
|
+
version: 0.17.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- LemonTree55
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-08-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: strptime
|
|
@@ -40,6 +40,7 @@ files:
|
|
|
40
40
|
- lib/rasn1.rb
|
|
41
41
|
- lib/rasn1/errors.rb
|
|
42
42
|
- lib/rasn1/model.rb
|
|
43
|
+
- lib/rasn1/model/accel.rb
|
|
43
44
|
- lib/rasn1/tracer.rb
|
|
44
45
|
- lib/rasn1/types.rb
|
|
45
46
|
- lib/rasn1/types/any.rb
|
|
@@ -91,14 +92,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
91
92
|
requirements:
|
|
92
93
|
- - ">="
|
|
93
94
|
- !ruby/object:Gem::Version
|
|
94
|
-
version: 3.
|
|
95
|
+
version: 3.1.0
|
|
95
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
97
|
requirements:
|
|
97
98
|
- - ">="
|
|
98
99
|
- !ruby/object:Gem::Version
|
|
99
100
|
version: '0'
|
|
100
101
|
requirements: []
|
|
101
|
-
rubygems_version: 3.
|
|
102
|
+
rubygems_version: 3.3.27
|
|
102
103
|
signing_key:
|
|
103
104
|
specification_version: 4
|
|
104
105
|
summary: Ruby ASN.1 library
|