0

I have a complicated nested ASN.1 structure as bytes. I want to find all T61Strings (say) in that structure, in the original byte encoding. Is this possible in pyasn1?

So far, I only know how to locate the the T61Strings (or whatever) in the BER-decoded Python object. I could re-encode each one, but there's no guarantee that the re-encoded values would match the originals. There's some crypto in play here, hence the fussiness about those byte values.

If I could just do decoded_object.get_substrate(), or similar, I'd be sorted.

Thoughts? Thanks.


Update: Ilya Etingof's answer seems to work nicely.

In [61]: class X(pyasn1.codec.ber.decoder.Decoder):
    ...:     def __call__(self,*v,**kw):
    ...:         parsed,remainder = pyasn1.codec.ber.decoder.Decoder.__call__(self,*v,**kw)
    ...:         parsed._substrate = v[0][:len(v[0])-len(remainder)]
    ...:         return parsed,remainder
    ...:     

In [62]: decode = X(pyasn1.codec.ber.decoder.tagMap,pyasn1.codec.ber.decoder.typeMap)

In [63]: tmp = decode(b'\x30\x05\x02\x01\x7f\x05\x00')[0]

In [64]: tmp._substrate.encode('hex')
Out[64]: '300502017f0500'

In [65]: tmp[0]._substrate.encode('hex')
Out[65]: '02017f'

In [66]: tmp[1]._substrate.encode('hex')
Out[66]: '0500'

In [67]: 
  • Are you able to read your structure with pyasn1 already? In other words, do you have a python-pyasn1 or ASN1 schema for the structure definition of your particular format, or is your requirement to read any arbitrary formats? – battlmonstr May 11 '18 at 19:50
  • @battlmonstr, I have a schema. – PythonAteMyHamster May 11 '18 at 20:36

1 Answers1

1

Is it BER, not DER? Crypto applications tend to use DER because it's stable. If it'a DER you should be able to safely re-encode once decoded items and get the same outcome.

There is no built-in feature in pyasn1 that allows you matching substrate fragments to decoded objects. But you can probably simulate that by overriding Decoder.call() method and taking note of its substrate + length parameters to see what's being decoded and the return value of the overridden __call__() method which is the object produced from the substrate you observe.

Keep in mind that decoding process is recursive so you will see both terminal (scalar) and container objects containing many others.

Ilya Etingof
  • 5,440
  • 1
  • 17
  • 21
  • Thanks, that seemed to work. See my first post (now updated) ... is that what you had in mind? – PythonAteMyHamster May 12 '18 at 17:05
  • @PythonAteMyHamster Exactly, though I'd probably pass a mutable object through `kwargs` to pass the substrate out of the call (rather than assigning it to the decoder object's attribute). Or may be attach the substrate to the decoded asn.1 object...? – Ilya Etingof May 14 '18 at 06:24