如果有适当的key
和iv
,此C程序应加密stdin
,输出到stdout
。
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit(ctx, EVP_aes_256_gcm(), key, iv);
const size_t block_size = 128;
unsigned char inbuf[block_size];
unsigned char outbuf[block_size + EVP_MAX_BLOCK_LENGTH];
int inlen, outlen;
for (;;)
{
inlen = fread(inbuf, 1, block_size, stdin);
if (inlen <= 0)
break;
EVP_EncryptUpdate(ctx, outbuf, &outlen, inbuf, inlen)
fwrite(outbuf, 1, outlen, stdout);
}
EVP_EncryptFinal_ex(ctx, outbuf, &outlen)
fwrite(outbuf, 1, outlen, stdout);
(为简洁起见,删除了错误检查。)
我正在通过运行
来验证此代码的输出 openssl aes-256-gcm -in ciphertext.txt -K <key> -iv <iv> -d
这成功且可靠地解密了密文,但之后写了 bad decrypt ,例如
$ openssl aes-256-gcm ...
Hello World.
bad decrypt
导致它说出来可能会出错?
答案 0 :(得分:0)
我在加密后完全无法获得GCM身份验证标记,然后在解密期间提供它。
“解密错误”消息具有误导性 - 解密正常,但未提供提供身份验证的标记。
使用
调用EVP_EncryptFinal_ex
后可以获取标记
unsigned char *tag = malloc(TAGSIZE);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAGSIZE, tag);
TAGSIZE
是标记的大小(以字节为单位),可以是许多不同的值。这在Wikipedia以及其他地方进行了讨论。
答案 1 :(得分:-1)
这里的问题是,您没有像PKCS#7那样实现正确的填充。 openssl
期望在解码的消息中存在正确的填充。规则是:
现在使用AES-256,您的块大小为128位(16字节)。这意味着,您必须添加1-16个填充字节。要添加的填充字节始终是填充的 size ,因此如果必须添加9个字节的填充,则需要添加9个0x09
个字节。
如果您正确地将此填充添加到原始明文中,那么openssl应该停止在解密时抱怨。