I wrote the following code to decrypt the 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 also decrypted the file using OpenSSL:
openssl aes-128-cbc -d -in file.encrypted -out file.decrypted -iv $IV -K $KEY
The output file from Go is 8 bytes larger than the output file from OpenSSL.
Tail hexdump from file created 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 |........|
The tail of the hexdump from the file generated by the 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 added to the output of a file from Go?
EDIT:
As BJ Black explains, the reason for the extra bytes to exit my Go program is because PKCS is full.
The file is encrypted using AES in CBC mode, so regular text input should be a multiple of the block size, an addition 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 fill byte has a value equal to the total number of fill bytes, which in my case is 0x08 .
So, to find out the number of add-ons added to the file, you just need to read the last byte of the decrypted file and convert it to int:
paddingBytes := int(data[len(data)-1])
Then the WriteFile function can be changed as follows:
err = ioutil.WriteFile("file.decrypted", data[:len(data)-paddingBytes], 0644)
Now the output from my Go program is identical to the output from OpenSSL.