Skip to content

Commit eebdc49

Browse files
authored
Merge pull request #49 from lemontree55/fix048
RASN1.parse may now parse multiple elements from a DER string
2 parents 2d2df05 + 60cc464 commit eebdc49

File tree

3 files changed

+52
-14
lines changed

3 files changed

+52
-14
lines changed

lib/rasn1.rb

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,24 @@ module RASN1
2525
# generate {Types::Base} objects.
2626
# @param [String] der binary string to parse
2727
# @param [Boolean] ber if +true+, decode a BER string, else a DER one
28-
# @return [Types::Base]
28+
# @return [Types::Base, Array[Types::Base]]
2929
def self.parse(der, ber: false) # rubocop:disable Metrics/AbcSize
30-
type = Types.id2type(der)
31-
type.parse!(der, ber: ber)
30+
result = []
31+
until der.nil? || der.empty?
32+
type = Types.id2type(der)
33+
size = type.parse!(der, ber: ber)
3234

33-
if CONTAINER_CLASSES.include?(type.class)
34-
subder = type.value
35-
ary = []
36-
RASN1.tracer.tracing_level += 1 unless RASN1.tracer.nil?
37-
until subder.empty?
38-
ary << self.parse(subder)
39-
subder = subder[ary.last.to_der.size..]
35+
if CONTAINER_CLASSES.include?(type.class)
36+
RASN1.tracer.tracing_level += 1 unless RASN1.tracer.nil?
37+
content = self.parse(type.value)
38+
type.value = content.is_a?(Array) ? content : [content]
39+
RASN1.tracer.tracing_level -= 1 unless RASN1.tracer.nil?
4040
end
41-
RASN1.tracer.tracing_level -= 1 unless RASN1.tracer.nil?
42-
type.value = ary
41+
42+
result << type
43+
der = der[size..]
4344
end
44-
type
45+
46+
result.size == 1 ? result[0] : result
4547
end
4648
end

lib/rasn1/types/base.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ def self.encoded_type
9595
# Parse a DER or BER string
9696
# @param [String] der_or_ber string to parse
9797
# @param [Hash] options
98+
# @return [Base]
9899
# @option options [Boolean] :ber if +true+, parse a BER string, else a DER one
99100
# @note More options are supported. See {Base#initialize}.
100101
def self.parse(der_or_ber, options={})

spec/rasn1_spec.rb

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@
150150
expect(obj.value).to eq(RASN1::Types::Sequence.new(value: [@bool, @int]).to_der)
151151
end
152152

153-
context '(complex example)' do
153+
context '(complex examples)' do
154154
it 'decodes a complex example' do
155155
der = File.read(File.join(__dir__, 'cert_example.der')).b
156156
cert = RASN1.parse(der)
@@ -194,6 +194,41 @@
194194
expect(cert.value[0].value[7].constructed?).to eq(true)
195195
expect(cert.value[0].value[7].id).to eq(3)
196196
end
197+
198+
it 'decodes a 2-pass example' do
199+
der = ["303d040c800007db0300259e5d7f12860400a22b02046d192dad020100020100301d301b06132b060104018f5b067301010101288fc080c0000204ffffffff"].pack("H*")
200+
201+
# 1st pass
202+
pdu = RASN1.parse(der)
203+
expect(pdu).to be_a(RASN1::Types::Sequence)
204+
expect(pdu.value.size).to eq(3)
205+
expect(pdu.value[0]).to be_a(RASN1::Types::OctetString)
206+
expect(pdu.value[0].value.length).to eq(12)
207+
expect(pdu.value[1]).to be_a(RASN1::Types::OctetString)
208+
expect(pdu.value[1].value.length).to eq(0)
209+
expect(pdu.value[2]).to be_a(RASN1::Types::Base)
210+
expect(pdu.value[2].asn1_class).to eq(:context)
211+
expect(pdu.value[2].value.length).to eq(43)
212+
213+
# 2nd pass
214+
subpdus = RASN1.parse(pdu.value[2].value)
215+
expect(subpdus).to be_a(Array)
216+
expect(subpdus.size).to eq(4)
217+
expect(subpdus[0]).to be_a(RASN1::Types::Integer)
218+
expect(subpdus[0].to_i).to eq(1830366637)
219+
expect(subpdus[1]).to be_a(RASN1::Types::Integer)
220+
expect(subpdus[1].to_i).to eq(0)
221+
expect(subpdus[2]).to be_a(RASN1::Types::Integer)
222+
expect(subpdus[2].to_i).to eq(0)
223+
expect(subpdus[3]).to be_a(RASN1::Types::Sequence)
224+
expect(subpdus[3].value.size).to eq(1)
225+
expect(subpdus[3].value[0]).to be_a(RASN1::Types::Sequence)
226+
expect(subpdus[3].value[0].value.size).to eq(2)
227+
expect(subpdus[3].value[0].value[0]).to be_a(RASN1::Types::ObjectId)
228+
expect(subpdus[3].value[0].value[0].value).to eq("1.3.6.1.4.1.2011.6.115.1.1.1.1.40.4160757760")
229+
expect(subpdus[3].value[0].value[1]).to be_a(RASN1::Types::Integer)
230+
expect(subpdus[3].value[0].value[1].value).to eq(-1)
231+
end
197232
end
198233
end
199234
end

0 commit comments

Comments
 (0)