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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50b3f9ddc3a11279f36c21d14768a908b0fe4f22ff75d650791a7a58ac47eaa7
4
- data.tar.gz: d229ea04a626e34d8411e3787101ace2c55e3cef7178b617073ed6b65fefb867
3
+ metadata.gz: e7f6fe2fadbdb5b72ec51995e911ac9adc7efbf497708ca581c2870ed3622b31
4
+ data.tar.gz: 6b68a59752a7ee439a7401b51415070b51ef3241f65864d263c1da9bfcdb2290
5
5
  SHA512:
6
- metadata.gz: 37ea433265c6229a89d896e47918c242b2edc48c24ffa585873e3706dfc3eaf73628b76c91bad3e15e1d969a5caf52237c92336aefdba2668f63f9468e7e2004
7
- data.tar.gz: 0035453de20ea4873999ec18eb3065afa9f1fdddc2927f446ecd2b1851a3a0d1bef32b5bbc2d9029f804a57cd71fefbf95dae4cd4babae5f8491f1e9ea8057ad
6
+ metadata.gz: d67a67c02d381d92ca93552834cdfc5bce175dc31794020c1d39b3fcea6301a50393f1c964c94d04ef7e14b5593275e5f72873bc89097118ce1abe0c6e4c582a
7
+ data.tar.gz: 5f2a8486a6ec2709ab3ecae6b664a4a731394ee5ada28f8c5908734aaf20b3e485eb6f4f0d74dc25d238191875732e02299eda3ad5d765dd870b39bf880c3e3a
data/LICENSE CHANGED
@@ -1,6 +1,7 @@
1
1
  MIT License
2
2
 
3
3
  Copyright (c) 2017 Sylvain Daubert
4
+ Copyright (c) 2024 LemonTree55
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
7
  of this software and associated documentation files (the "Software"), to deal
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/sdaubert/rasn1/workflows/ci/badge.svg?branch=master)](https://github.com/sdaubert/rasn1/actions?query=workflow%3Aci)
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 [Hash,nil] content
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
- if self[subelt_name].is_a?(Model)
514
- elt = self[subelt_name][name]
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] = get_type(class_element.proc_or_class, self.class.options || {})
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
- next unless obj[name]
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 obj[name].is_a?(Model)
592
+ raise ArgumentError, "element #{name}: may only pass a Hash for Model elements" unless subobj.is_a?(Model)
585
593
 
586
- initialize_elements obj[name], value
594
+ initialize_elements(subobj, value)
587
595
  when Array
588
- initialize_element_from_array(obj[name], value)
596
+ initialize_element_from_array(subobj, value)
589
597
  else
590
- obj[name].value = value
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
- case wrap.element
667
+ el = wrap.element
668
+ case el
660
669
  when Model
661
- hsh = wrap.element.to_h
670
+ hsh = el.to_h
662
671
  hsh[hsh.keys.first]
663
672
  else
664
- private_to_h(wrap.element)
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 # rubocop:disable Lint/DuplicateMethods
79
- alias_method :do_parse_explicit, :do_parse_explicit_without_tracing # rubocop:disable Lint/DuplicateMethods
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 # rubocop:disable Lint/DuplicateMethods
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 # rubocop:disable Lint/DuplicateMethods
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 # rubocop:disable Lint/DuplicateMethods
161
+ alias_method :der_to_value, :der_to_value_without_tracing
162
162
  end
163
163
  end
164
164
 
@@ -61,7 +61,7 @@ module RASN1
61
61
  private
62
62
 
63
63
  def common_inspect(level)
64
- lvl = level >= 0 ? level : 0
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
- @value = der[0, total_length]
85
+ real_value = der[0, total_length].to_s
86
+ @value = real_value
86
87
 
87
- [total_length, @value]
88
+ [total_length, real_value]
88
89
  end
89
90
 
90
91
  def trace_any
@@ -374,7 +374,7 @@ module RASN1
374
374
  end
375
375
 
376
376
  def common_inspect(level)
377
- lvl = level >= 0 ? level : 0
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? asn1_class
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 == 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
- # Setter for constraint
13
- # @param [Proc,nil] constraint
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
- class << self
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] << ':' << zone[3, 2]
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
- others = date_hour.scan(/../).map(&:to_i)
85
- # Ruby 3.0
86
- # From 3.1: "Z" and "-0100" are supported
87
- # Below 3.1: should be "-01:00" or "+00:00"
88
- unless tz.nil?
89
- others += [0] * (5 - others.size)
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)
@@ -45,10 +45,12 @@ module RASN1
45
45
  # Integer value
46
46
  # @return [Integer]
47
47
  def to_i
48
- if @enum.empty?
49
- value? ? @value : @default || 0
48
+ val = value? ? @value : @default
49
+ case val
50
+ when String, Symbol
51
+ @enum[val]
50
52
  else
51
- @enum[value? ? @value : @default] || 0
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
- @value = der_to_int_value(der, ber: ber)
139
- return if @enum.empty?
140
-
141
- @value = int_to_enum(@value)
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!(&:to_i)
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
- ids.map! do |v|
21
- next v if v < 128
22
-
23
- unsigned_to_chained_octets(v)
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
- ids.flatten.pack('C*')
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 = if composed_of_type? && !@of_type.is_a?(Class)
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
- der.bytes.each_with_index do |octet, i|
42
- next if i.zero?
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 i + 1 if (octet & 0x80).zero?
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.nil? ? nil : block.to_proc
103
+ constraint = block&.to_proc
102
104
 
103
- new_klass = Class.new(from) do
104
- include Constrained
105
- end
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RASN1
4
- VERSION = '0.13.0'
4
+ VERSION = '0.13.1'
5
5
  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.13.0
4
+ version: 0.13.1
5
5
  platform: ruby
6
6
  authors:
7
- - Sylvain Daubert
7
+ - LemonTree55
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-03 00:00:00.000000000 Z
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
- - sylvain.daubert@laposte.net
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/sdaubert/rasn1
73
+ homepage: https://github.com/lemontree55/rasn1
74
74
  licenses:
75
75
  - MIT
76
76
  metadata:
77
- homepage_uri: https://github.com/sdaubert/rasn1
78
- source_code_uri: https://github.com/sdaubert/rasn1
79
- bug_tracker_uri: https://github.com/sdaubert/rasn1/issues
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: