decryption - AES/CBC

942 views
Skip to first unread message

Brian Ketelsen

unread,
Mar 8, 2011, 4:15:48 PM3/8/11
to golang-nuts
I'm decrypting strings with AES-256-cbc as follows:

decrypter := cipher.NewCBCDecrypter(c, iv)
decrypted = make([]byte, len(in))
decrypter.CryptBlocks(decrypted, in)

This works great, but the resulting byte array is padded up to the next block size with un-needed data. What step am I missing to determine the actual size of the decrypted value so I can return a slice of the actual data without the padding?

Thanks!

Brian

Russ Cox

unread,
Mar 8, 2011, 4:28:02 PM3/8/11
to Brian Ketelsen, golang-nuts
AES is a block-based protocol.
If you know how many bytes you expect,
then you can truncate the result yourself.
Otherwise I don't believe there is enough
information to figure that out.

Russ

peterGo

unread,
Mar 8, 2011, 6:21:57 PM3/8/11
to golang-nuts
Brian,

Are the values of the bytes used for padding arbitrary? Is the last
byte of the last block the count or the count minus one of the padding
bytes?

Peter

Brian Ketelsen

unread,
Mar 8, 2011, 7:41:34 PM3/8/11
to peterGo, golang-nuts
It is, Peter. It's the count of the padding bytes [7] [7] [7] [7] [7] [7] [7]

I was thinking I could check for that case and strip out 7 * 0x07 or 6 * 0x06, etc. I know that my input strings are never going to have non-printable characters, too, so I was thinking generically I could drop any bytes values at 15 or under, since they'd be the most possible padding.

OpenSSL is doing this process automatically, both in the C library that we're using from MySQL , and the Ruby bindings to OpenSSL that we're using from our application. Dropping the bytes under 16 would work, as would checking for repeated bytes under 15. I can go look at the OpenSSL source code and see what they're doing for maximum compatibility.

I asked if I was doing something wrong or missing something because the OpenSSL C library returns a length integer that is the length of the actual decrypted string without the extra padding. I was thinking there would be a similar Go function. It's easy enough to implement, either way.

Thanks for the help.

Brian

Russ Cox

unread,
Mar 8, 2011, 8:38:30 PM3/8/11
to Brian Ketelsen, peterGo, golang-nuts
It's likely that OpenSSL is doing some kind of framing beyond
the encryption and then undoing it for you. The Go library
only implements the cryptography itself and leaves the
framing to other programs, since it is not standardized.

If you do implement the framing yourself, note the possible
padding lengths must be from 1 to 16, not 0 to 15. Otherwise
you cannot unpad unambiguously.

Russ

pascal bertrand

unread,
Mar 8, 2011, 9:39:32 PM3/8/11
to r...@golang.org, Brian Ketelsen, peterGo, golang-nuts
This is good old PKCS7 padding. I believe it is the most widespread but there are other padding schemes.

Better leave freedom to use whichever you want.


Pascal BERTRAND

Brian Ketelsen

unread,
Mar 8, 2011, 11:59:30 PM3/8/11
to golang-nuts
Thank you all for the input. I implemented PKCS7 padding which is what OpenSSL was using, and my input/output from Go matches input/output from both my C based mysql user defined function and Ruby implementation. Success.

Brian

Reply all
Reply to author
Forward
0 new messages