rasn2 0.16.0 → 1.0.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/lib/{rasn1 → rasn2}/errors.rb +2 -2
- data/lib/rasn2/helpers/colorize.rb +119 -0
- data/lib/{rasn1 → rasn2}/model.rb +16 -12
- data/lib/{rasn1 → rasn2}/schema_parser.rb +10 -10
- data/lib/{rasn1 → rasn2}/tracer.rb +15 -14
- data/lib/{rasn1 → rasn2}/types/any.rb +18 -34
- data/lib/{rasn1 → rasn2}/types/base.rb +120 -82
- data/lib/{rasn1 → rasn2}/types/bit_string.rb +3 -6
- data/lib/{rasn1 → rasn2}/types/bmp_string.rb +1 -1
- data/lib/{rasn1 → rasn2}/types/boolean.rb +2 -2
- data/lib/{rasn1 → rasn2}/types/choice.rb +5 -5
- data/lib/{rasn1 → rasn2}/types/constrained.rb +2 -2
- data/lib/{rasn1 → rasn2}/types/constructed.rb +1 -24
- data/lib/{rasn1 → rasn2}/types/enumerated.rb +3 -3
- data/lib/{rasn1 → rasn2}/types/generalized_time.rb +1 -1
- data/lib/{rasn1 → rasn2}/types/ia5_string.rb +5 -1
- data/lib/{rasn1 → rasn2}/types/integer.rb +3 -2
- data/lib/{rasn1 → rasn2}/types/null.rb +6 -5
- data/lib/{rasn1 → rasn2}/types/numeric_string.rb +1 -1
- data/lib/{rasn1 → rasn2}/types/object_id.rb +1 -1
- data/lib/{rasn1 → rasn2}/types/octet_string.rb +3 -6
- data/lib/{rasn1 → rasn2}/types/primitive.rb +1 -1
- data/lib/{rasn1 → rasn2}/types/printable_string.rb +1 -1
- data/lib/{rasn1 → rasn2}/types/sequence.rb +6 -6
- data/lib/{rasn1 → rasn2}/types/sequence_of.rb +20 -25
- data/lib/{rasn1 → rasn2}/types/set.rb +5 -5
- data/lib/{rasn1 → rasn2}/types/set_of.rb +1 -1
- data/lib/{rasn1 → rasn2}/types/tag.rb +13 -28
- data/lib/{rasn1 → rasn2}/types/universal_string.rb +1 -1
- data/lib/{rasn1 → rasn2}/types/utc_time.rb +1 -1
- data/lib/{rasn1 → rasn2}/types/utf8_string.rb +1 -1
- data/lib/{rasn1 → rasn2}/types/visible_string.rb +1 -1
- data/lib/{rasn1 → rasn2}/types.rb +7 -5
- data/lib/{rasn1 → rasn2}/value_notation.rb +5 -5
- data/lib/rasn2/version.rb +6 -0
- data/lib/{rasn1 → rasn2}/wrapper.rb +8 -15
- data/lib/{rasn1.rb → rasn2.rb} +14 -14
- metadata +40 -40
- data/lib/rasn1/helpers/colorize.rb +0 -76
- data/lib/rasn1/version.rb +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0bc40f5198815e03f0bfa923321ac614e68d4587f31b3cb18d999f40e7b49004
|
|
4
|
+
data.tar.gz: '09ec989aa9f0674cf2f4ed956518bd717a85de33357b7c09cd2fe6a2d2caa9b8'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7739ea22723954d0ee78787697e8dde59bb0b41f6fb3c23c8e34f0cab1bd23720b35e05abffb8ac389141115f598d61cf28ce32ccd7d078169cf16bf0043616c
|
|
7
|
+
data.tar.gz: e5ef77bb7b20f1bb6819c4935e04a302c58930bc183371b132522c0b245da9e306de8fbcb29653c535c8d6646f991ff990726466937f487a5c7ea0470034a342
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
3
|
+
module RASN2
|
|
4
4
|
# Base error class
|
|
5
5
|
class Error < StandardError; end
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ module RASN1
|
|
|
19
19
|
class EnumeratedError < Error; end
|
|
20
20
|
|
|
21
21
|
# CHOICE error: {Types::Choice#chosen} not set
|
|
22
|
-
class ChoiceError <
|
|
22
|
+
class ChoiceError < RASN2::Error
|
|
23
23
|
# @param [Types::Base] object
|
|
24
24
|
def initialize(object)
|
|
25
25
|
@object = object
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RASN2
|
|
4
|
+
module Helpers
|
|
5
|
+
module Colorize
|
|
6
|
+
def colorizer
|
|
7
|
+
@colorizer&.first || Rainbow.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def colorizer=(colorizer)
|
|
11
|
+
@colorizer ||= []
|
|
12
|
+
@colorizer << colorizer
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def begin_colorizer(color)
|
|
16
|
+
@colorizer ||= []
|
|
17
|
+
@colorizer << Rainbow.new
|
|
18
|
+
@colorizer.last.enabled = color
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def colorize(msg)
|
|
22
|
+
colorizer.wrap(msg)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def end_colorizer
|
|
26
|
+
@colorizer&.pop
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def parens_hex(input, padding=2)
|
|
30
|
+
value = if input.is_a?(Integer)
|
|
31
|
+
if input >= 0
|
|
32
|
+
value = "%0#{padding}X" % input
|
|
33
|
+
value = value.rjust((value.length + 1) / 2 * 2, '0')
|
|
34
|
+
"0x#{value}"
|
|
35
|
+
else
|
|
36
|
+
'0xFF'
|
|
37
|
+
end
|
|
38
|
+
else
|
|
39
|
+
input
|
|
40
|
+
end
|
|
41
|
+
"#{colorize('(').webgray}#{colorize(value).blue}#{colorize(')').webgray}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def int_with_hex(input, raw_value=nil)
|
|
45
|
+
if raw_value.nil?
|
|
46
|
+
"#{colorize(input).blue} #{parens_hex(input)}"
|
|
47
|
+
else
|
|
48
|
+
"#{colorize(input).blue} #{parens_hex(raw_value)}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def brace_surround(input)
|
|
53
|
+
"#{colorize('[').webgray} #{input} #{colorize(']').webgray}"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def colorize_class(name, tag_id=nil, *attributes)
|
|
57
|
+
parts = [colorize(name).bold.yellow]
|
|
58
|
+
parts += attributes.map { |attr| colorize_attribute(attr) } if attributes.any?
|
|
59
|
+
parts << parens_hex(tag_id) if tag_id
|
|
60
|
+
parts.join(' ')
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def colorize_id(id, tag_class=nil)
|
|
64
|
+
id = id.strip if id.is_a? String
|
|
65
|
+
tag_class = tag_class.strip if tag_class.is_a? String
|
|
66
|
+
tag_class = '' if tag_class == 'UNIVERSAL'
|
|
67
|
+
|
|
68
|
+
return '' if id.to_s == '' && tag_class.to_s == ''
|
|
69
|
+
|
|
70
|
+
if tag_class && tag_class != ''
|
|
71
|
+
brace_surround("#{colorize_class(tag_class)} #{colorize(id).bold.green}")
|
|
72
|
+
else
|
|
73
|
+
brace_surround(colorize(id).bold.green)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def length_specifier(data_length, encoded_length=nil)
|
|
78
|
+
encoded_length = data_length if encoded_length.nil?
|
|
79
|
+
"#{colorize('len:').gray} #{colorize(data_length).blue} #{parens_hex(encoded_length)}"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def colorize_name(name)
|
|
83
|
+
colorize(name).bold.white
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def colorize_attribute(attribute)
|
|
87
|
+
colorize(attribute).bold.magenta
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def colorize_default(value)
|
|
91
|
+
" #{colorize_attribute('DEFAULT VALUE')} #{colorize(value).green.bold}"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def colorize_nil(name='NONE')
|
|
95
|
+
colorize(name).red.bold
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def colorize_enum(name, raw_value)
|
|
99
|
+
raw_value = "0x#{raw_value.unpack1('H*').upcase}" if raw_value.is_a?(String)
|
|
100
|
+
"#{colorize_class(name)} #{parens_hex(raw_value)}"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def colorize_value(value)
|
|
104
|
+
colorize(value).blue
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def colorize_bool(value, raw_value)
|
|
108
|
+
hex_raw_value = raw_value.is_a?(String) ? "0x#{raw_value.unpack1('H*').upcase}" : raw_value
|
|
109
|
+
value = if value
|
|
110
|
+
colorize('TRUE').bold.green
|
|
111
|
+
else
|
|
112
|
+
colorize('FALSE').bold.red
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
"#{value} #{parens_hex(hex_raw_value)}"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
3
|
+
module RASN2
|
|
4
4
|
# @abstract
|
|
5
5
|
# {Model} class is a base class to define ASN.1 models.
|
|
6
6
|
# == Create a simple ASN.1 model
|
|
@@ -11,7 +11,7 @@ module RASN1
|
|
|
11
11
|
# house [1] EXPLICIT INTEGER DEFAULT 0
|
|
12
12
|
# }
|
|
13
13
|
# you may create your model like this:
|
|
14
|
-
# class Record <
|
|
14
|
+
# class Record < RASN2::Model
|
|
15
15
|
# sequence(:record,
|
|
16
16
|
# content: [integer(:id),
|
|
17
17
|
# integer(:room, implicit: 0, optional: true),
|
|
@@ -20,7 +20,7 @@ module RASN1
|
|
|
20
20
|
#
|
|
21
21
|
# Since 0.17.0, content may also be defined through a block. This is strictly
|
|
22
22
|
# equivalent to the +:content+ option:
|
|
23
|
-
# class Record <
|
|
23
|
+
# class Record < RASN2::Model
|
|
24
24
|
# sequence :record do
|
|
25
25
|
# integer :id
|
|
26
26
|
# integer :room, implicit: 0, optional: true
|
|
@@ -28,7 +28,7 @@ module RASN1
|
|
|
28
28
|
# end
|
|
29
29
|
# end
|
|
30
30
|
# Blocks may be nested, and may use all model helpers (+#model+, +#wrapper+, +#sequence_of+, ...):
|
|
31
|
-
# class PersonnelRecord <
|
|
31
|
+
# class PersonnelRecord < RASN2::Model
|
|
32
32
|
# sequence :personnelRecord do
|
|
33
33
|
# utf8_string :name
|
|
34
34
|
# utf8_string :title
|
|
@@ -43,7 +43,7 @@ module RASN1
|
|
|
43
43
|
#
|
|
44
44
|
# === Parse a DER-encoded string
|
|
45
45
|
# record = Record.parse(der_string)
|
|
46
|
-
# record[:id] # =>
|
|
46
|
+
# record[:id] # => RASN2::Types::Integer
|
|
47
47
|
# record[:id].value # => Integer
|
|
48
48
|
# record[:id].to_i # => Integer
|
|
49
49
|
# record[:id].asn1_class # => Symbol
|
|
@@ -61,7 +61,7 @@ module RASN1
|
|
|
61
61
|
#
|
|
62
62
|
# == Create a more complex model
|
|
63
63
|
# Models may be nested. For example:
|
|
64
|
-
# class Record2 <
|
|
64
|
+
# class Record2 < RASN2::Model
|
|
65
65
|
# sequence(:record2,
|
|
66
66
|
# content: [boolean(:rented, default: false),
|
|
67
67
|
# model(:a_record, Record)])
|
|
@@ -74,7 +74,7 @@ module RASN1
|
|
|
74
74
|
# or like this:
|
|
75
75
|
# record2 = Record2.new(rented: true, a_record: { id: 65537, room: 43 })
|
|
76
76
|
# Same model, using a block:
|
|
77
|
-
# class Record2 <
|
|
77
|
+
# class Record2 < RASN2::Model
|
|
78
78
|
# sequence :record2 do
|
|
79
79
|
# boolean :rented, default: false
|
|
80
80
|
# model :a_record, Record
|
|
@@ -129,6 +129,8 @@ module RASN1
|
|
|
129
129
|
# @private Sequence types
|
|
130
130
|
SEQUENCE_TYPES = [Types::Sequence, Types::SequenceOf, Types::Set, Types::SetOf].freeze
|
|
131
131
|
|
|
132
|
+
include Helpers::Colorize
|
|
133
|
+
|
|
132
134
|
# Define helper methods to define models
|
|
133
135
|
module Accel # rubocop:disable Metrics/ModuleLength
|
|
134
136
|
# @return [Hash]
|
|
@@ -193,7 +195,7 @@ module RASN1
|
|
|
193
195
|
|
|
194
196
|
# Update options of root element.
|
|
195
197
|
# May be used when subclassing.
|
|
196
|
-
# class Model1 <
|
|
198
|
+
# class Model1 < RASN2::Model
|
|
197
199
|
# sequence :seq, implicit: 0,
|
|
198
200
|
# content: [bool(:bool), integer(:int)]
|
|
199
201
|
# end
|
|
@@ -567,7 +569,9 @@ module RASN1
|
|
|
567
569
|
# @return [Integer] number of parsed bytes
|
|
568
570
|
# @raise [ASN1Error] error on parsing
|
|
569
571
|
def parse!(der, ber: false)
|
|
570
|
-
root.parse!(der, ber: ber)
|
|
572
|
+
result = root.parse!(der, ber: ber)
|
|
573
|
+
result.model = self if result.respond_to? :model=
|
|
574
|
+
result
|
|
571
575
|
end
|
|
572
576
|
|
|
573
577
|
# @private
|
|
@@ -587,10 +591,10 @@ module RASN1
|
|
|
587
591
|
# @return [Object,nil]
|
|
588
592
|
# @return [Object,nil]
|
|
589
593
|
# @example
|
|
590
|
-
# class MyModel1 <
|
|
594
|
+
# class MyModel1 < RASN2::Model
|
|
591
595
|
# sequence('seq', content: [boolean('boolean'), integer('int')])
|
|
592
596
|
# end
|
|
593
|
-
# class MyModel2 <
|
|
597
|
+
# class MyModel2 < RASN2::Model
|
|
594
598
|
# sequence('root', content: [sequence_of('list', MyModel1)])
|
|
595
599
|
# end
|
|
596
600
|
# model = MyModel2.new
|
|
@@ -634,7 +638,7 @@ module RASN1
|
|
|
634
638
|
|
|
635
639
|
# @return [String]
|
|
636
640
|
def inspect(level=0, color: true)
|
|
637
|
-
|
|
641
|
+
root.inspect(level, color: color, kind: type)
|
|
638
642
|
end
|
|
639
643
|
|
|
640
644
|
# Objects are equal if they have same class AND same DER
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
3
|
+
module RASN2
|
|
4
4
|
# Parser for ASN.1 text schema definitions.
|
|
5
5
|
#
|
|
6
6
|
# Parses ASN.1 module definitions and generates {Model} subclasses from them.
|
|
7
7
|
#
|
|
8
8
|
# @example Parse a schema file
|
|
9
|
-
# models =
|
|
10
|
-
# # => { 'PersonnelRecord' => PersonnelRecord (class <
|
|
9
|
+
# models = RASN2::SchemaParser.parse_file('path/to/schema.asn')
|
|
10
|
+
# # => { 'PersonnelRecord' => PersonnelRecord (class < RASN2::Model) }
|
|
11
11
|
#
|
|
12
12
|
# @example Parse a schema string
|
|
13
13
|
# schema = <<~ASN1
|
|
@@ -19,12 +19,12 @@ module RASN1
|
|
|
19
19
|
# }
|
|
20
20
|
# END
|
|
21
21
|
# ASN1
|
|
22
|
-
# models =
|
|
22
|
+
# models = RASN2::SchemaParser.parse(schema)
|
|
23
23
|
#
|
|
24
24
|
# @author rickmark
|
|
25
25
|
# @since 0.16.0
|
|
26
26
|
module SchemaParser
|
|
27
|
-
# ASN.1 type name to
|
|
27
|
+
# ASN.1 type name to RASN2 type DSL method mapping
|
|
28
28
|
TYPE_MAP = {
|
|
29
29
|
'BOOLEAN' => :boolean,
|
|
30
30
|
'INTEGER' => :integer,
|
|
@@ -45,10 +45,10 @@ module RASN1
|
|
|
45
45
|
}.freeze
|
|
46
46
|
|
|
47
47
|
# Constructed type names
|
|
48
|
-
CONSTRUCTED_TYPES = %w[SEQUENCE SET].freeze
|
|
48
|
+
CONSTRUCTED_TYPES = %w[SEQUENCE SET TAG].freeze
|
|
49
49
|
|
|
50
50
|
# Error raised when parsing an ASN.1 schema fails
|
|
51
|
-
class ParseError <
|
|
51
|
+
class ParseError < RASN2::Error; end
|
|
52
52
|
|
|
53
53
|
class << self
|
|
54
54
|
# Parse an ASN.1 schema from a file and generate Model classes.
|
|
@@ -348,7 +348,7 @@ module RASN1
|
|
|
348
348
|
# Build a single Model subclass
|
|
349
349
|
# @return [Class]
|
|
350
350
|
def build_model_class(type_name, type_def, mod, existing_models, namespace)
|
|
351
|
-
klass = Class.new(
|
|
351
|
+
klass = Class.new(RASN2::Model)
|
|
352
352
|
|
|
353
353
|
root_name = type_name.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').downcase.to_sym
|
|
354
354
|
|
|
@@ -445,14 +445,14 @@ module RASN1
|
|
|
445
445
|
# (end of private section)
|
|
446
446
|
end
|
|
447
447
|
|
|
448
|
-
# Convert an ASN.1 type name to the corresponding
|
|
448
|
+
# Convert an ASN.1 type name to the corresponding RASN2 Model DSL method symbol
|
|
449
449
|
# @param [String] type_name
|
|
450
450
|
# @return [Symbol, nil]
|
|
451
451
|
def self.type_to_method(type_name)
|
|
452
452
|
TYPE_MAP[type_name]
|
|
453
453
|
end
|
|
454
454
|
|
|
455
|
-
# Convert an ASN.1 type name to the corresponding
|
|
455
|
+
# Convert an ASN.1 type name to the corresponding RASN2::Types class
|
|
456
456
|
# @param [String] type_name
|
|
457
457
|
# @return [Class, nil]
|
|
458
458
|
def self.type_to_class(type_name)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'rainbow'
|
|
4
4
|
|
|
5
|
-
module
|
|
5
|
+
module RASN2
|
|
6
6
|
# @private
|
|
7
7
|
class Tracer
|
|
8
8
|
# @return [IO]
|
|
@@ -37,7 +37,8 @@ module RASN1
|
|
|
37
37
|
# @param [String] msg
|
|
38
38
|
# @return [void]
|
|
39
39
|
def trace(msg)
|
|
40
|
-
|
|
40
|
+
indented = msg.split("\n").map { |line| indent + line }.join("\n")
|
|
41
|
+
@io.puts(indented)
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
# Return identation for given +level+. If +nil+, use {#tracing_level}.
|
|
@@ -45,23 +46,23 @@ module RASN1
|
|
|
45
46
|
# @return [String]
|
|
46
47
|
def indent(level=nil)
|
|
47
48
|
level ||= @tracing_level
|
|
48
|
-
|
|
49
|
+
" " * level
|
|
49
50
|
end
|
|
50
51
|
end
|
|
51
52
|
|
|
52
|
-
# Trace
|
|
53
|
+
# Trace RASN2 parsing to +io+.
|
|
53
54
|
# All parsing methods called in block are traced to +io+. Each ASN.1 element is
|
|
54
55
|
# traced in a line showing element's id, its length and its data.
|
|
55
56
|
# @param [IO] io
|
|
56
57
|
# @param [Boolean] color enable colorized output using pastel gem (requires pastel to be installed)
|
|
57
58
|
# @example
|
|
58
|
-
#
|
|
59
|
-
#
|
|
59
|
+
# RASN2.trace do
|
|
60
|
+
# RASN2.parse("\x02\x01\x01") # puts "INTEGER id: 2 (0x02), len: 1 (0x01), data: 0x01"
|
|
60
61
|
# end
|
|
61
|
-
#
|
|
62
|
+
# RASN2.parse("\x01\x01\xff") # puts nothing onto STDOUT
|
|
62
63
|
# @example with color
|
|
63
|
-
#
|
|
64
|
-
#
|
|
64
|
+
# RASN2.trace(color: true) do
|
|
65
|
+
# RASN2.parse("\x02\x01\x01") # same output but with ANSI colors
|
|
65
66
|
# end
|
|
66
67
|
# @return [void]
|
|
67
68
|
def self.trace(io=$stdout, color: false)
|
|
@@ -142,7 +143,7 @@ module RASN1
|
|
|
142
143
|
# Parse +der+ with tracing abillity
|
|
143
144
|
# @see #parse!
|
|
144
145
|
def parse_with_tracing(der, ber: false)
|
|
145
|
-
|
|
146
|
+
RASN2.tracer.trace(self.trace)
|
|
146
147
|
parse_without_tracing(der, ber: ber)
|
|
147
148
|
end
|
|
148
149
|
end
|
|
@@ -166,9 +167,9 @@ module RASN1
|
|
|
166
167
|
# @private
|
|
167
168
|
# der_to_value +der+ with tracing abillity
|
|
168
169
|
def der_to_value_with_tracing(der, ber: false)
|
|
169
|
-
|
|
170
|
+
RASN2.tracer.tracing_level += 1
|
|
170
171
|
der_to_value_without_tracing(der, ber: ber)
|
|
171
|
-
|
|
172
|
+
RASN2.tracer.tracing_level -= 1
|
|
172
173
|
end
|
|
173
174
|
end
|
|
174
175
|
|
|
@@ -191,9 +192,9 @@ module RASN1
|
|
|
191
192
|
# @private
|
|
192
193
|
# der_to_value +der+ with tracing abillity
|
|
193
194
|
def der_to_value_with_tracing(der, ber: false)
|
|
194
|
-
|
|
195
|
+
RASN2.tracer.tracing_level += 1
|
|
195
196
|
der_to_value_without_tracing(der, ber: ber)
|
|
196
|
-
|
|
197
|
+
RASN2.tracer.tracing_level -= 1
|
|
197
198
|
end
|
|
198
199
|
end
|
|
199
200
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
3
|
+
module RASN2
|
|
4
4
|
module Types
|
|
5
5
|
# ASN.1 ANY: accepts any types
|
|
6
6
|
#
|
|
@@ -31,67 +31,51 @@ module RASN1
|
|
|
31
31
|
# @param [Boolean] ber if +true+, accept BER encoding
|
|
32
32
|
# @return [Integer] total number of parsed bytes
|
|
33
33
|
def parse!(der, ber: false)
|
|
34
|
-
total_length,
|
|
34
|
+
total_length, data = do_parse(der, ber: ber)
|
|
35
|
+
@value = data
|
|
35
36
|
total_length
|
|
36
37
|
end
|
|
37
38
|
|
|
38
|
-
# @param [::Integer] level
|
|
39
|
-
# @return [String]
|
|
40
|
-
def inspect(level=0)
|
|
41
|
-
str = common_inspect(level)
|
|
42
|
-
str << if !value?
|
|
43
|
-
'NULL'
|
|
44
|
-
elsif @value.is_a?(OctetString) || @value.is_a?(BitString)
|
|
45
|
-
"#{@value.type}: #{value.value.inspect}"
|
|
46
|
-
elsif @value.class < Base
|
|
47
|
-
"#{@value.type}: #{value.value}"
|
|
48
|
-
else
|
|
49
|
-
value.to_s.inspect
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
39
|
# @private Tracer private API
|
|
54
40
|
# @return [String]
|
|
55
41
|
def trace
|
|
56
42
|
return trace_any if value?
|
|
57
43
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def common_inspect(level)
|
|
64
|
-
lvl = [0, level].max
|
|
65
|
-
str = ' ' * lvl
|
|
66
|
-
str << "#{@name} " unless @name.nil?
|
|
67
|
-
str << asn1_class.to_s.upcase << ' ' unless asn1_class == :universal
|
|
68
|
-
str << "[#{id}] EXPLICIT " if explicit?
|
|
69
|
-
str << "[#{id}] IMPLICIT " if implicit?
|
|
70
|
-
str << '(ANY) '
|
|
44
|
+
parts = []
|
|
45
|
+
parts << msg_type(no_id: true)
|
|
46
|
+
parts << colorize_nil
|
|
47
|
+
parts.reject(&:empty?).join(' ')
|
|
71
48
|
end
|
|
72
49
|
|
|
73
50
|
# @private
|
|
74
51
|
# @see Types::Base#do_parse
|
|
75
52
|
def do_parse(der, ber: false)
|
|
53
|
+
asn1_class, _pc, id, id_size = Types.decode_identifier_octets(der)
|
|
54
|
+
@id = id
|
|
55
|
+
@asn1_class = asn1_class
|
|
56
|
+
|
|
76
57
|
if der.empty?
|
|
77
58
|
return [0, ''] if optional?
|
|
78
59
|
|
|
79
60
|
raise ASN1Error, 'Expected ANY but get nothing'
|
|
80
61
|
end
|
|
81
62
|
|
|
82
|
-
id_size = Types.decode_identifier_octets(der).last
|
|
83
63
|
total_length, = get_data(der[id_size..], ber)
|
|
84
64
|
total_length += id_size
|
|
85
65
|
|
|
86
66
|
@no_value = false
|
|
87
67
|
real_value = der[0, total_length].to_s
|
|
88
|
-
@value =
|
|
68
|
+
@value = if constructed?
|
|
69
|
+
RASN2.parse(real_value, ber: ber)
|
|
70
|
+
else
|
|
71
|
+
real_value
|
|
72
|
+
end
|
|
89
73
|
|
|
90
|
-
[total_length,
|
|
74
|
+
[total_length, @value]
|
|
91
75
|
end
|
|
92
76
|
|
|
93
77
|
def trace_any
|
|
94
|
-
msg_type(no_id:
|
|
78
|
+
"#{msg_type(no_id: false)}#{trace_data(value)}"
|
|
95
79
|
end
|
|
96
80
|
end
|
|
97
81
|
end
|