John Smith
John Smith

Reputation: 391

Different result when decrypting file in Go and OpenSSL

I have written the following code to decrypt a file:

data, err := ioutil.ReadFile("file.encrypted")
if err != nil {
    log.Fatal(err)
}

block, err := aes.NewCipher(key)
if err != nil {
    log.Fatal(err)
}

mode := cipher.NewCBCDecrypter(block, iv)

mode.CryptBlocks(data, data)

err = ioutil.WriteFile("file.decrypted", data, 0644)
if err != nil {
    log.Fatal(err)
}

I have also decrypted the file using OpenSSL:

openssl aes-128-cbc -d -in file.encrypted -out file.decrypted -iv $IV -K $KEY

Output file from Go program is 8 bytes larger than output file from from OpenSSL.

Tail of hexdump from file generated by OpenSSL:

ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
ff ff ff ff ff ff ff ff                           |........|

Tail of hexdump from file generated by Go program:

ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
ff ff ff ff ff ff ff ff  08 08 08 08 08 08 08 08  |................|

Why is 08 08 08 08 08 08 08 08 appended to file output from Go program?

EDIT:

As BJ Black explains, the reason for extra bytes in output from my Go program is PKCS padding.

The file is encrypted with AES in CBC mode and therefore the plain text input shall be a multiple of block size, padding is added to fulfill this requirement. AES has a block size of 16 bytes so the total number of padding bytes will always be between 1 and 16 bytes. Each padding byte has a value equal to the total number of padding bytes which in my case is 0x08.

So, to find out the amount of padding added to the file, one just have to read the last byte of decrypted file and convert that number to int:

paddingBytes := int(data[len(data)-1])

The WriteFile function can then be modified like this:

err = ioutil.WriteFile("file.decrypted", data[:len(data)-paddingBytes], 0644)

Now output from my Go program is identical to the output from OpenSSL.

Upvotes: 5

Views: 208

Answers (1)

BJ Black
BJ Black

Reputation: 2521

What you're seeing is PKCS padding, which OSSL is removing for you and Go isn't by default. See the relevant Reddit post here.

Basically, follow the example and you're good to go.

Upvotes: 3

Related Questions