rasn1 0.16.1 → 0.16.3

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.
@@ -9,7 +9,18 @@
9
9
  module RASN1
10
10
  module Types
11
11
  # ASN.1 Bit String
12
+ #
13
+ # A BIT STRING is a primitive ASN.1 type, able to embbed data whose length is not multiple of a byte.
14
+ #
15
+ # To specify a non byte multiple length, +:bit_length+ option must be used.
16
+ #
17
+ # @example Simple bit string
18
+ # # A 4-bit length bit string, with value 1000b
19
+ # bs = RASN1::Types::BitString.new(value: "\x80", bit_length: 4)
20
+ # # As DER/BER encode data on bytes, such encodings specify unused part in binary string
21
+ # bs.to_der #=> "\x03\x02\x04\x80"
12
22
  # @author Sylvain Daubert
23
+ # @author LemonTree55
13
24
  class BitString < Primitive
14
25
  # BitString id value
15
26
  ID = 3
@@ -17,10 +28,9 @@ module RASN1
17
28
  # @return [Integer]
18
29
  attr_writer :bit_length
19
30
 
20
- # @param [Hash] options
31
+ # @!macro type_initialize
21
32
  # @option options [Object] :bit_length default bit_length value. Should be
22
33
  # present if +:default+ is set
23
- # @see Base#initialize common options to all ASN.1 types
24
34
  def initialize(options={})
25
35
  super
26
36
  if @default
@@ -40,7 +50,7 @@ module RASN1
40
50
  end
41
51
  end
42
52
 
43
- # @param [Integer] level
53
+ # @param level [Integer]
44
54
  # @return [String]
45
55
  def inspect(level=0)
46
56
  str = common_inspect(level)
@@ -55,8 +65,8 @@ module RASN1
55
65
  end
56
66
 
57
67
  # Make value from DER/BER string. Also set {#bit_length}.
58
- # @param [String] der
59
- # @param [::Boolean] ber
68
+ # @param der [String]
69
+ # @param ber [::Boolean]
60
70
  # @return [void]
61
71
  # @see Types::Base#der_to_value
62
72
  def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
@@ -70,6 +80,7 @@ module RASN1
70
80
 
71
81
  # @author Sylvain Daubert
72
82
  # @author adfoster-r7
83
+ # @return [String]
73
84
  def value_to_der
74
85
  raise ASN1Error, "#{@name}: bit length is not set" if bit_length.nil?
75
86
 
@@ -89,6 +100,7 @@ module RASN1
89
100
  der
90
101
  end
91
102
 
103
+ # @return [String]
92
104
  def generate_value_with_correct_length
93
105
  value = (@value || '').dup.force_encoding('BINARY')
94
106
  value << "\x00".b while value.length * 8 < @bit_length.to_i
@@ -98,6 +110,7 @@ module RASN1
98
110
  value[0, max_len].to_s
99
111
  end
100
112
 
113
+ # @return [BitString]
101
114
  def explicit_type
102
115
  self.class.new(name: name, value: @value, bit_length: @bit_length)
103
116
  end
@@ -9,7 +9,16 @@
9
9
  module RASN1
10
10
  module Types
11
11
  # ASN.1 Boolean
12
+ #
13
+ # BOOLEAN is a primitive type to handle true or false values.
14
+ # @example Booelan
15
+ # bool = RASN1::Types::Boolean.new(value: true)
16
+ # bool2 = RASN1.parse(bool.to_der)
17
+ # bool2.class #=> RASN1::Types::Boolean
18
+ # bool3.value #=> true
19
+ #
12
20
  # @author Sylvain Daubert
21
+ # @author LemonTree55
13
22
  class Boolean < Primitive
14
23
  # Boolean id value
15
24
  ID = 0x01
@@ -25,8 +34,8 @@ module RASN1
25
34
  end
26
35
 
27
36
  # Make boolean value from DER/BER string.
28
- # @param [String] der
29
- # @param [::Boolean] ber
37
+ # @param der [String]
38
+ # @param ber [::Boolean]
30
39
  # @return [void]
31
40
  # @see Types::Base#der_to_value
32
41
  # @raise [ASN1Error] +der+ is not 1-byte long
@@ -49,14 +58,16 @@ module RASN1
49
58
 
50
59
  private
51
60
 
61
+ # @return [String]
52
62
  def value_to_der
53
63
  [@value ? DER_TRUE : DER_FALSE].pack('C')
54
64
  end
55
65
 
66
+ # @return [String]
56
67
  def trace_data
57
68
  return super if explicit?
58
69
 
59
- " #{raw_data == "\x00".b ? 'FALSE' : 'TRUE'} (0x#{raw_data.unpack1('H*')})"
70
+ " #{raw_data == "\x00".b ? 'FALSE' : 'TRUE'} (0x#{bin2hex(raw_data)})"
60
71
  end
61
72
  end
62
73
  end
@@ -10,32 +10,44 @@ module RASN1
10
10
  module Types
11
11
  # A ASN.1 CHOICE is a choice between different types.
12
12
  #
13
- # == Create a CHOICE
14
- # A CHOICE is defined this way:
13
+ # @example Create a CHOICE
15
14
  # choice = Choice.new
16
15
  # choice.value = [Integer.new(implicit: 0, class: :context),
17
16
  # Integer.new(implicit: 1, class: :context),
18
17
  # OctetString.new(implicit: 2, class: :context)]
19
- # The chosen type may be set this way:
20
- # choice.chosen = 0 # choose :int1
21
- # The chosen value may be set these ways:
18
+ # # Choose an element
19
+ # choice.chosen = 0 # choose int1
20
+ # # Set chosen value
22
21
  # choise.value[choice.chosen].value = 1
23
- # choise.set_chosen_value 1
24
- # The chosen value may be got these ways:
22
+ # # Also set chosen value
23
+ # choise.set_chosen_value(1)
24
+ # # Got chosen value
25
25
  # choise.value[choice.chosen].value # => 1
26
26
  # choice.chosen_value # => 1
27
27
  #
28
- # == Encode a CHOICE
29
- # {#to_der} only encodes the chosen value:
30
- # choise.to_der # => "\x80\x01\x01"
28
+ # @example Encode a CHOICE
29
+ # choice = Choice.new
30
+ # choice.value = [Integer.new(implicit: 0, class: :context, value: 1),
31
+ # Integer.new(implicit: 1, class: :context),
32
+ # OctetString.new(implicit: 2, class: :context, value: "a")]
33
+ # # to_der only encodes the chosen value
34
+ # choice.chosen = 0 # choose int1
35
+ # choice.to_der # => "\x80\x01\x01"
36
+ # # another choice, another encoding string
37
+ # choice.chosen_value = 2
38
+ # choice.to_der # => "\x82\x01a"
31
39
  #
32
- # == Parse a CHOICE
33
- # Parsing a CHOICE set {#chosen} and set value to chosen type. If parsed string does
34
- # not contain a type from CHOICE, a {RASN1::ASN1Error} is raised.
35
- # str = "\x04\x03abc"
36
- # choice.parse! str
40
+ # @example Parse a CHOICE
41
+ # choice = Choice.new
42
+ # choice.value = [Integer.new(implicit: 0, class: :context, value: 1),
43
+ # Integer.new(implicit: 1, class: :context),
44
+ # OctetString.new(implicit: 2, class: :context, value: "a")]
45
+ # # Parse an octet string
46
+ # choice.parse!("\x82\x03abc")
37
47
  # choice.chosen # => 2
38
48
  # choice.chosen_value # => "abc"
49
+ # # Parse an unexpected value
50
+ # choice.parse!("\x04\x03abc") # => RASN1::ASN1Error
39
51
  # @author Sylvain Daubert
40
52
  class Choice < Base
41
53
  # Chosen type
@@ -44,7 +56,7 @@ module RASN1
44
56
 
45
57
  # Set chosen value.
46
58
  # @note {#chosen} MUST be set before calling this method
47
- # @param [Object] value
59
+ # @param value [Object]
48
60
  # @return [Object] value
49
61
  # @raise [ChoiceError] {#chosen} not set
50
62
  def set_chosen_value(value) # rubocop:disable Naming/AccessorMethodName
@@ -68,9 +80,10 @@ module RASN1
68
80
  end
69
81
  end
70
82
 
71
- # @note {#chosen} MUST be set before calling this method
83
+ # Encode Choice into DER encoding
72
84
  # @return [String] DER-formated string
73
85
  # @raise [ChoiceError] {#chosen} not set
86
+ # @note {#chosen} MUST be set before calling this method
74
87
  def to_der
75
88
  check_chosen
76
89
  @value[@chosen].to_der
@@ -78,8 +91,8 @@ module RASN1
78
91
 
79
92
  # Parse a DER string. This method updates object by setting {#chosen} and
80
93
  # chosen value.
81
- # @param [String] der DER string
82
- # @param [Boolean] ber if +true+, accept BER encoding
94
+ # @param der [String] DER string
95
+ # @param ber [Boolean] if +true+, accept BER encoding
83
96
  # @return [Integer] total number of parsed bytes
84
97
  # @raise [ASN1Error] error on parsing
85
98
  def parse!(der, ber: false)
@@ -96,6 +109,7 @@ module RASN1
96
109
  end
97
110
 
98
111
  # @private
112
+ # @!macro do_parse
99
113
  # @see Types::Base#do_parse
100
114
  # @since 0.15.0 Specific +#do_parse+ to handle recursivity
101
115
  def do_parse(der, ber: false)
@@ -115,8 +129,8 @@ module RASN1
115
129
  end
116
130
 
117
131
  # Make choice value from DER/BER string.
118
- # @param [String] der
119
- # @param [::Boolean] ber
132
+ # @param der [String]
133
+ # @param ber [::Boolean]
120
134
  # @return [void]
121
135
  # @since 0.15.0 Specific +#der_to_value+ to handle recursivity
122
136
  def der_to_value(der, ber: false)
@@ -130,7 +144,7 @@ module RASN1
130
144
  end
131
145
  end
132
146
 
133
- # @param [::Integer] level
147
+ # @param level [::Integer]
134
148
  # @return [String]
135
149
  def inspect(level=0)
136
150
  str = common_inspect(level)
@@ -148,7 +162,7 @@ module RASN1
148
162
  end
149
163
 
150
164
  # Return empty array
151
- # @return [Array()]
165
+ # @return [Array]
152
166
  # @since 0.15.0
153
167
  def void_value
154
168
  []
@@ -156,6 +170,8 @@ module RASN1
156
170
 
157
171
  private
158
172
 
173
+ # @return [void]
174
+ # @raise [ChoiceError] {#chosen} is not set
159
175
  def check_chosen
160
176
  raise ChoiceError.new(self) if !defined?(@chosen) || @chosen.nil?
161
177
  end
@@ -25,7 +25,7 @@ module RASN1
25
25
  end
26
26
 
27
27
  # Check constraint, if defined
28
- # @param [Object] value the value of the type to check
28
+ # @param value [Object] the value of the type to check
29
29
  # @raise [ConstraintError] constraint is not verified
30
30
  def check_constraint(value)
31
31
  return unless constrained?
@@ -36,6 +36,7 @@ module RASN1
36
36
  extend ClassMethods
37
37
 
38
38
  # Redefined +#value=+ to check constraint before assigning +val+
39
+ # @!macro value_setter
39
40
  # @see Types::Base#value=
40
41
  # @raise [ConstraintError] constraint is not verified
41
42
  def value=(val)
@@ -44,8 +45,8 @@ module RASN1
44
45
  end
45
46
 
46
47
  # Make value from +der+ string and check constraints
47
- # @param [String] der
48
- # @param [::Boolean] ber
48
+ # @param der [String]
49
+ # @param ber [::Boolean]
49
50
  # @return [void]
50
51
  # @raise [ConstraintError] constraint is not verified
51
52
  def der_to_value(der, ber: false)
@@ -10,7 +10,9 @@ module RASN1
10
10
  module Types
11
11
  # @abstract This class SHOULD be used as base class for all ASN.1 primitive
12
12
  # types.
13
- # Base class for all ASN.1 constructed types
13
+ # This is the base class for all ASN.1 constructed types. A constructed type combines similar or different
14
+ # {Primitive primitive} types into ordered or unordered groups
15
+ #
14
16
  # @author Sylvain Daubert
15
17
  class Constructed < Base
16
18
  # Constructed value
@@ -30,7 +32,7 @@ module RASN1
30
32
  end
31
33
  end
32
34
 
33
- # @param [::Integer] level (default: 0)
35
+ # @param level [::Integer] (default: 0)
34
36
  # @return [String]
35
37
  def inspect(level=0)
36
38
  case @value
@@ -10,18 +10,19 @@ module RASN1
10
10
  module Types
11
11
  # ASN.1 Enumerated
12
12
  #
13
- # An enumerated type permits to assign names to integer values. It may be defined
14
- # different ways:
13
+ # An ENUMERATED type permits to assign names to integer values. {Integer} may
14
+ # also be enumerated, but the tag {ID} is different.
15
+ #
16
+ # @example Example 1
15
17
  # enum = RASN1::Types::Enumerated.new(enum: { 'a' => 0, 'b' => 1, 'c' => 2 })
18
+ # enum.value = 'a'
19
+ # enum.value # => 'a'
20
+ # @example Example 2
16
21
  # enum = RASN1::Types::Enumerated.new(enum: { a: 0, b: 1, c: 2 })
17
- # Its value should be setting as an Integer or a String/symbol:
18
22
  # enum.value = :b
19
23
  # enum.value = 1 # equivalent to :b
20
- # But its value is always stored as named integer:
21
- # enum.value = :b
22
- # enum.value # => :b
23
- # enum.value = 0
24
- # enum.value # => :a
24
+ # # enum returned value is always symbolic (even if set with an integer)
25
+ # enum.value # => :b
25
26
  # A {EnumeratedError} is raised when set value is not in enumeration.
26
27
  # @author Sylvain Daubert
27
28
  class Enumerated < Integer
@@ -15,26 +15,29 @@ module RASN1
15
15
  # +{#value} of a {GeneralizedTime} should be a ruby Time.
16
16
  #
17
17
  # ===Notes
18
- # When encoding, resulting string is always a UTC time, appended with +Z+.
18
+ # On encoding, resulting string is always a UTC time, appended with +Z+.
19
19
  # Minutes and seconds are always generated. Fractions of second are generated
20
20
  # if value Time object have them.
21
21
  #
22
- # On parsing, are supported:
22
+ # On parsing, this class supports:
23
23
  # * UTC times (ending with +Z+),
24
24
  # * local times (no suffix),
25
25
  # * local times with difference between UTC and this local time (ending with
26
26
  # +sHHMM+, where +s+ is +++ or +-+, and +HHMM+ is the time differential
27
27
  # betwen UTC and local time).
28
28
  # These times may include minutes and seconds. Fractions of hour, minute and
29
- # second are supported.
29
+ # second are also supported.
30
30
  # @author Sylvain Daubert
31
+ # @author LemonTree55
31
32
  class GeneralizedTime < Primitive
32
33
  # GeneralizedTime id value
33
34
  ID = 24
34
35
 
35
36
  # @private
37
+ # Second count in one hour
36
38
  HOUR_TO_SEC = 3600
37
39
  # @private
40
+ # Second count in one minute
38
41
  MINUTE_TO_SEC = 60
39
42
  # @private
40
43
  SECOND_TO_SEC = 1
@@ -51,8 +54,8 @@ module RASN1
51
54
  end
52
55
 
53
56
  # Make time value from +der+ string
54
- # @param [String] der
55
- # @param [::Boolean] ber
57
+ # @param der [String]
58
+ # @param ber [::Boolean]
56
59
  # @return [void]
57
60
  def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
58
61
  date_hour, fraction = der.split('.')
@@ -70,6 +73,7 @@ module RASN1
70
73
 
71
74
  private
72
75
 
76
+ # @return [String]
73
77
  def value_to_der
74
78
  utc_value = @value.getutc
75
79
  if utc_value.nsec.positive?
@@ -80,6 +84,9 @@ module RASN1
80
84
  end
81
85
  end
82
86
 
87
+ # Set internal value to a Time defined from date and hour from +date_hour+, without fraction.
88
+ # @param date_hour [String]
89
+ # @return [void]
83
90
  def value_when_fraction_empty(date_hour)
84
91
  tz = compute_tz(date_hour)
85
92
  year = date_hour.slice!(0, 4).to_i
@@ -91,9 +98,13 @@ module RASN1
91
98
  @value = Time.new(year, month, day, hour, minute, second, tz)
92
99
  end
93
100
 
94
- # Ruby 3.0: special handle for timezone
95
- # From 3.1: "Z" and "-0100" are supported
96
- # Below 3.1: should be "-01:00" or "+00:00"
101
+ # Compute TZ from +date_hour+ string
102
+ # @param date_hour [String]
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"
97
108
  def compute_tz(date_hour)
98
109
  if date_hour.end_with?('Z')
99
110
  date_hour.slice!(-1, 1)
@@ -106,6 +117,10 @@ module RASN1
106
117
  end
107
118
  end
108
119
 
120
+ # Set value in special case where fraction ends with 'Z'
121
+ # @param date_hour [String]
122
+ # @param fraction [String]
123
+ # @return [void]
109
124
  def value_when_fraction_ends_with_z(date_hour, fraction)
110
125
  fraction = fraction[0...-1]
111
126
  date_hour << 'Z'
@@ -114,6 +129,10 @@ module RASN1
114
129
  fix_value(fraction, frac_base)
115
130
  end
116
131
 
132
+ # Set value in general case
133
+ # @param date_hour [String]
134
+ # @param fraction [String]
135
+ # @return [void]
117
136
  def value_on_others_cases(date_hour, fraction)
118
137
  match = fraction.match(/(\d+)([+-]\d+)/)
119
138
  if match
@@ -127,11 +146,18 @@ module RASN1
127
146
  fix_value(fraction, frac_base)
128
147
  end
129
148
 
149
+ # Fix internal value with +fraction+, based on +frac_base+
150
+ # @param fraction [String]
151
+ # @param frac_base [::Integer]
152
+ # @return [void]
130
153
  def fix_value(fraction, frac_base)
131
154
  frac = ".#{fraction}".to_r * frac_base
132
155
  @value = (@value + frac) unless fraction.nil?
133
156
  end
134
157
 
158
+ # Compute fraction base from +date_hour+ string
159
+ # @param date_hour [String]
160
+ # @return [::Integer]
135
161
  def compute_frac_base(date_hour)
136
162
  case date_hour.size
137
163
  when 10, 11
@@ -152,6 +178,7 @@ module RASN1
152
178
  end
153
179
  end
154
180
 
181
+ # @return [String]
155
182
  def trace_data
156
183
  return super if explicit?
157
184
 
@@ -9,25 +9,50 @@
9
9
  module RASN1
10
10
  module Types
11
11
  # ASN.1 Integer
12
+ #
13
+ # An INTEGER is a primitive type to represent integers.
14
+ # There is no limit on integer size.
15
+ #
16
+ # @example Simple Integers
17
+ # # Simple integer with a value associated
18
+ # int1 = RASN1::Types::Integer.new(value: 42)
19
+ # # Integer without value, but a default one
20
+ # int2 = RASN1::Types::Integer.new(default: -42)
21
+ #
22
+ # @example Enumerated Integer
23
+ # enum = RASN1::Types::Integer.new(enum: {one: 1, two: 2})
24
+ # enum.value = :two
25
+ # enum.value #=> :two
26
+ # enum.to_i #=> 2
12
27
  # @author Sylvain Daubert
28
+ # @author LemonTree55
13
29
  class Integer < Primitive
14
- # @return [Hash,nil]
30
+ # Associated enumeration
31
+ # @return [Hash{String=>::Integer},nil]
15
32
  attr_reader :enum
16
33
 
17
34
  # Integer id value
18
35
  ID = 2
19
36
 
20
- # @option options [Hash] :enum enumeration hash. Keys are names, and values
37
+ # @!macro type_initialize
38
+ # @option options [Hash{String=>::Integer}] :enum enumeration hash. Keys are names, and values
21
39
  # are integers.
22
40
  # @raise [EnumeratedError] +:default+ value is unknown when +:enum+ key is present
23
- # @see Base#initialize common options to all ASN.1 types
24
41
  def initialize(options={})
25
42
  super
26
43
  initialize_enum(@options[:enum])
27
44
  end
28
45
 
29
- # @param [Integer,String,Symbol,nil] val
46
+ # Set integer value from a Ruby integer, or a String or a Symbol (only when {#enum} is defined).
47
+ # @param val [::Integer,String,Symbol,nil]
30
48
  # @return [void]
49
+ # @note
50
+ # An enumerated INTEGER may be set with an integer value out of enumeration,
51
+ # only when no value is set.
52
+ # @raise [EnumeratedError] string/symbol value: no enum defined or +val+ not in enum
53
+ # @raise [EnumeratedError] integer value: value already set and new value not in enum
54
+ # @raise [TypeError] unsupported +val+ type
55
+ # @since 0.16.2 raise TypeError (was EnumeratedError)
31
56
  def value=(val)
32
57
  @no_value = false
33
58
  case val
@@ -39,17 +64,17 @@ module RASN1
39
64
  @no_value = true
40
65
  @value = void_value
41
66
  else
42
- raise EnumeratedError, "#{@name}: not in enumeration"
67
+ raise TypeError, "#{val.class} not supported"
43
68
  end
44
69
  end
45
70
 
46
- # @return [Integer]
71
+ # @return [::Integer]
47
72
  def void_value
48
73
  0
49
74
  end
50
75
 
51
76
  # Integer value
52
- # @return [Integer]
77
+ # @return [::Integer]
53
78
  def to_i
54
79
  val = value? ? @value : @default
55
80
  case val
@@ -61,8 +86,8 @@ module RASN1
61
86
  end
62
87
 
63
88
  # Make integer value from +der+ string.
64
- # @param [String] der
65
- # @param [::Boolean] ber
89
+ # @param der [String]
90
+ # @param ber [::Boolean]
66
91
  # @return [void]
67
92
  def der_to_value(der, ber: false)
68
93
  int_value = der_to_int_value(der, ber: ber)
@@ -75,6 +100,9 @@ module RASN1
75
100
 
76
101
  private
77
102
 
103
+ # Initialize integer with given enum hash.
104
+ # @param enum [Hash{String=>::Integer}]
105
+ # @return [void]
78
106
  def initialize_enum(enum)
79
107
  @enum = enum || {}
80
108
  return if @enum.empty?
@@ -85,6 +113,10 @@ module RASN1
85
113
  check_enum_default
86
114
  end
87
115
 
116
+ # Check defined default is coherent with enum
117
+ # @return [void]
118
+ # @raise [EnumeratedError] default value not defined in {#enum}
119
+ # @raise [TypeError] unsupported type for default value
88
120
  def check_enum_default
89
121
  case @default
90
122
  when String, Symbol
@@ -99,6 +131,10 @@ module RASN1
99
131
  end
100
132
  end
101
133
 
134
+ # Set value from given string or symbol value
135
+ # @param val [String,Symbol]
136
+ # @return [void]
137
+ # @raise [EnumeratedError] no enum defined or +val+ not in enum
102
138
  def value_from_string_or_symbol(val)
103
139
  raise EnumeratedError, "#{@name} has no :enum" if @enum.empty?
104
140
  raise EnumeratedError, "#{@name}: unknwon enumerated value #{val}" unless @enum.key? val
@@ -106,6 +142,10 @@ module RASN1
106
142
  @value = val
107
143
  end
108
144
 
145
+ # Set value from given integer value.
146
+ # @param val [::Integer]
147
+ # @return [void]
148
+ # @raise [EnumeratedError] +val+ not in enum
109
149
  def value_from_integer(val)
110
150
  if @enum.empty?
111
151
  @value = val
@@ -116,6 +156,8 @@ module RASN1
116
156
  end
117
157
  end
118
158
 
159
+ # @param value [::Integer]
160
+ # @return [String]
119
161
  def int_value_to_der(value)
120
162
  size = compute_size(value)
121
163
  comp_value = value >= 0 ? value : (~(-value) + 1) & ((1 << (size * 8)) - 1)
@@ -125,12 +167,16 @@ module RASN1
125
167
  ary.reverse.pack('C*')
126
168
  end
127
169
 
170
+ # Get size in bytes of +value+ integer
171
+ # @param value [::Integer]
172
+ # @return [::Integer]
128
173
  def compute_size(value)
129
174
  size = value.bit_length / 8 + ((value.bit_length % 8).positive? ? 1 : 0)
130
175
  size = 1 if size.zero?
131
176
  size
132
177
  end
133
178
 
179
+ # @return [String]
134
180
  def value_to_der
135
181
  case @value
136
182
  when String, Symbol
@@ -142,6 +188,9 @@ module RASN1
142
188
  end
143
189
  end
144
190
 
191
+ # @param der [String]
192
+ # @param ber [::Boolean]
193
+ # @return [::Integer]
145
194
  def der_to_int_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
146
195
  ary = der.unpack('C*')
147
196
  v = ary.reduce(0) { |len, b| (len << 8) | b }
@@ -149,22 +198,29 @@ module RASN1
149
198
  v
150
199
  end
151
200
 
201
+ # Return value to show (enumerated if enum is defined, else integer)
202
+ # @param int [::Integer]
203
+ # @param check_enum [::Boolean]
204
+ # @return [String,::Integer]
205
+ # @raise [EnumeratedError] +check_enum+ is +true+, enum is defined, and +int+ is not in enum
152
206
  def int_to_enum(int, check_enum: true)
153
207
  raise EnumeratedError, "#{@name}: value #{int} not in enumeration" if check_enum && !@enum.value?(int)
154
208
 
155
209
  @enum.key(int) || int
156
210
  end
157
211
 
212
+ # @return [::Integer]
158
213
  def explicit_type
159
214
  self.class.new(name: name, enum: enum)
160
215
  end
161
216
 
217
+ # @return [String]
162
218
  def trace_data
163
219
  return super if explicit?
164
- return " #{der_to_int_value(raw_data)} (0x#{raw_data.unpack1('H*')})" if @enum.empty?
220
+ return " #{der_to_int_value(raw_data)} (0x#{bin2hex(raw_data)})" if @enum.empty?
165
221
 
166
222
  v = int_to_enum(der_to_int_value(raw_data), check_enum: false)
167
- " #{v} (0x#{raw_data.unpack1('H*')})"
223
+ " #{v} (0x#{bin2hex(raw_data)})"
168
224
  end
169
225
  end
170
226
  end
@@ -9,11 +9,14 @@
9
9
  module RASN1
10
10
  module Types
11
11
  # ASN.1 Null
12
+ #
13
+ # This type is a placeholder when a value is not mandatory (in a {Choice}, by example).
12
14
  # @author Sylvain Daubert
13
15
  class Null < Primitive
14
16
  # Null id value
15
17
  ID = 0x05
16
18
 
19
+ # @param level [Integer]
17
20
  # @return [String]
18
21
  def inspect(level=0)
19
22
  str = common_inspect(level)[0..-2] # remove terminal ':'
@@ -21,15 +24,15 @@ module RASN1
21
24
  str
22
25
  end
23
26
 
24
- # @return [Boolean]
25
27
  # Build only if not optional
28
+ # @return [Boolean]
26
29
  def can_build?
27
30
  !optional?
28
31
  end
29
32
 
30
33
  # Check +der+ string
31
- # @param [String] der
32
- # @param [::Boolean] ber
34
+ # @param der [String]
35
+ # @param ber [::Boolean]
33
36
  # @return [void]
34
37
  # @raise [ASN1Error] +der+ is not empty
35
38
  def der_to_value(der, ber: false) # rubocop:disable Lint/UnusedMethodArgument
@@ -41,6 +44,7 @@ module RASN1
41
44
 
42
45
  private
43
46
 
47
+ # @return [String]
44
48
  def value_to_der
45
49
  ''
46
50
  end