在Go和OpenSSL中解密文件时的结果不同

Joh*_*ith 5 encryption go

我编写了以下代码来解密文件:

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)
}
Run Code Online (Sandbox Code Playgroud)

我还使用OpenSSL解密了该文件:

openssl aes-128-cbc -d -in file.encrypted -out file.decrypted -iv $IV -K $KEY
Run Code Online (Sandbox Code Playgroud)

Go程序的输出文件比OpenSSL的输出文件大8个字节.

从OpenSSL生成的文件中的hexdump尾:

ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
ff ff ff ff ff ff ff ff                           |........|
Run Code Online (Sandbox Code Playgroud)

从Go程序生成的文件中的hexdump尾:

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  |................|
Run Code Online (Sandbox Code Playgroud)

为什么要08 08 08 08 08 08 08 08附加到Go程序的文件输出?

编辑:

正如BJ Black解释的那样,我的Go程序输出中额外字节的原因是PKCS填充.

该文件在CBC模式下使用AES加密,因此纯文本输入应为块大小的倍数,添加填充以满足此要求.AES的块大小为16字节,因此填充字节总数将始终在1到16个字节之间.每个填充字节的值等于填充字节的总数,在我的例子中0x08.

因此,要找出添加到文件中的填充量,只需读取解密文件的最后一个字节并将该数字转换为int:

paddingBytes := int(data[len(data)-1])
Run Code Online (Sandbox Code Playgroud)

然后可以像这样修改WriteFile函数:

err = ioutil.WriteFile("file.decrypted", data[:len(data)-paddingBytes], 0644)
Run Code Online (Sandbox Code Playgroud)

现在我的Go程序输出与OpenSSL的输出相同.

BJ *_*ack 3

您看到的是 PKCS 填充,OSSL 正在为您删除它,而 Go 默认情况下不会删除它。请参阅此处的相关 Reddit 帖子。

基本上,按照示例操作就可以了。