Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASN1 decoding: how to ignore padding? #91

Closed
HoneyryderChuck opened this issue Dec 13, 2016 · 5 comments
Closed

ASN1 decoding: how to ignore padding? #91

HoneyryderChuck opened this issue Dec 13, 2016 · 5 comments

Comments

@HoneyryderChuck
Copy link

I'm using the ASN1 to decode information which had been previously encrypted. It was decrypted also using openssl (DES interface), and it came out padded. Let's say, for the sake of argument, the stream was \x02\x01\x00\x00, where the last \x00 is padding. I'd expect to call ASN1.decode and have it decode it to the integer, but instead it fails:

pry> OpenSSL::ASN1.decode("\x02\x01\x00\x00")
OpenSSL::ASN1::ASN1Error: Type mismatch. Total bytes read: 3 Bytes available: 4 Offset: 3
from (pry):14:in `decode'

Is there a way to accomplish this? Or am I forced to inspect the length bytes and remove the padding myself?

@rhenium
Copy link
Member

rhenium commented Dec 15, 2016

Because "\x02\x01\x00\x00" is not a valid BER encoding, it is expected that OpenSSL::ASN1.decode refuses to parse. Why do you use such a nonreversible padding?

@HoneyryderChuck
Copy link
Author

not exactly me, but it's the result of decrypting an SNMPv3 encrypted PDU. I'm also using openssl for the decryption, and am explicitly setting the padding to 0, as specified in the rfc. Along these lines:

cipher = Cipher::DES.new(:CBC)
cipher.decrypt
cipher.padding = 0
cipher.key = key
cipher.iv = iv
data = cipher.update(encrypted_pdu) + cipher.final
# data was padded before encryption, so a BER-encoded PDU might have length 77, while the decrypted
# part might be length 80
# what to do here to safely remove padding before decoding?

And this is my question. Right now, I'm slicing all \x00 from the resulting decrypted payload. But this is not a solution, as the last value can be a ber-encoded null, or a ber-encoded integer with value 0, and that would mess up my decoding.

The example I gave you might not be a valid BER encoding, but I thought there could be an hidden API which would ignore bytes which aren't part of a BER-encoded sequence, and so on, like:

stream = "0\x03\x02\x01\x00\x02\x01\x00"
OpenSSL::ASN1.decode stream

This will fail with a type mismatch error, but it also could just decode the sequence and ignore the subsequence integer, with, let's say, an imaginary argument ignore_mismatches: true.

Anyway, this is just an idea. I'd totally understand if this weren't to be supported, and would appreciate any kind of suggestions you'd have on remove padding from deciphered payloads, as I don't have currently any idea on how to do that besides the faulty patch I mentioned above.

@rhenium
Copy link
Member

rhenium commented Dec 15, 2016

The protocol doesn't seem to give the actual content length. That's unfortunate.

I however think such an option is useful in too limited situations to provide from the openssl library.

In this case, I think you can workaround by inspecting the real content length with OpenSSL::ASN1.traverse[1]:

str = "\x02\x01\x00\x00"
headerlen, bodylen = OpenSSL::ASN1.traverse(str) { |_, _, x, y, *| break x, y }
decoded = OpenSSL::ASN1.decode(str.byteslice(0, headerlen+bodylen))

[1] http://ruby.github.io/openssl/OpenSSL/ASN1.html#method-c-traverse

@HoneyryderChuck
Copy link
Author

The protocol does give the content length (in that case, it's an integer with size 1 and value 0, it would work the same for sequences). You need to decode it first, however. It is possible, and something that the library could do, but you know the situations in which this part of openssl is used better than me.

The workaround with traverse does seem to solve my issue. I'll have a quick try in a few minutes and will let you know. Thx for the tip!

@HoneyryderChuck
Copy link
Author

It did the trick. Thx Again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants