为什么 aes_128_cbc() 工作但 aes_128_gcm() 对于 encryption/decryption 使用 EVP?
Why does aes_128_cbc() work but not aes_128_gcm() for encryption/decryption using EVP?
下面的代码使用了 aes_128_cbc 并且它正确地加密了代码,但是当我将它更改为 aes_128_gcm 时,没有输出 encrypted.The 下面的代码是我原来的工作代码。我的密钥是128位(长度16)而且iv也是长度16。
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <string.h>
EVP_CIPHER_CTX *ctx;
char key[]="somerandomkey123"; /*length 16*/
char output[1024];
char input[]= "Message here.";
int len;
FILE *binfile;
if(!ctx = EVP_CIPHER_CTX_new()){
(error message)
}
if(1 != EVP_EncryptInit_ex(ctx,EVP_aes_128_cbc(),NULL,key,"[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]\")){
(error message)
}
if(1 != EVP_EncryptUpdate(ctx,output,&len,input,strlen(input))){
(error message)
}
if(1 != EVP_EncryptFinal_ex(ctx, output+len, &len)){
(error message)
}
EVP_CIPHER_CTX_free(ctx)
/*This prints out 0 when I change cbc to gcm, but prints a correct size when I use cbc*/
printf("Output size: %d \n", len);
/*Properly writes to file when cbc used but not when gcm used. Nothing is in encrypted.bin when gcm is used when encrypted text should be there.*/
binfile = fopen("encrypted.bin","wb");
fwrite(outbuf,len,1,binfile);
当我将 EVP_aes_128_cbc() 更改为 EVP_aes_128_gcm() 时,代码不再有效。我还将 iv 更改为长度 12 ("[=22=][=22=][=22=][=22=][=22=][=22=][=22=][=22=][=22=][=22=][=22=][=22=]")。最后,我在 EVP_EncryptFinal_ex:
之后添加了这个代码块
char tag[] = "1234567890123456";
if(1 != EVP_CIPHER_CTX_ctrl(ctx,EVP_CTRL_GCM_GET_TAG,16,tag)){
(error message)
}
打印时我的最终输出大小为 0,里面什么也没有(在原始代码中注明)。我的问题是,当我只将 cbc 更改为 gcm 时,为什么我没有得到任何加密?是因为 key/iv 大小问题还是更大?
EncryptUpdate 和 EncryptFinal 都添加到输出缓冲区(或不添加)。
碰巧,对于您的短明文消息,在 CBC 模式下,所有输出均由 EncryptFinal 写入,而对于 GCM 模式,所有输出均由 EncryptUpdate 写入。
您代码中的问题在于,您在 EncryptUpdate 和 EncryptFinal 中重复使用了 "len" 变量。他们都(覆盖)写入 len 由调用添加的数据量。因此,在 CBC 模式下,EncryptFinal 会用 16 覆盖初始值 0,而在 GCM 模式下,初始值 13 会被 0 覆盖。
您应该按照 openssl wiki (https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption) 中的说明进行操作:
/* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertext_len = len;
/* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
handleErrors();
ciphertext_len += len;
顺便说一句:如果只是文本,您可以继续使用 strlen 作为输入数据的长度,但请记住,这不会加密零终止符,因此您必须在解密后手动添加它。
下面的代码使用了 aes_128_cbc 并且它正确地加密了代码,但是当我将它更改为 aes_128_gcm 时,没有输出 encrypted.The 下面的代码是我原来的工作代码。我的密钥是128位(长度16)而且iv也是长度16。
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <string.h>
EVP_CIPHER_CTX *ctx;
char key[]="somerandomkey123"; /*length 16*/
char output[1024];
char input[]= "Message here.";
int len;
FILE *binfile;
if(!ctx = EVP_CIPHER_CTX_new()){
(error message)
}
if(1 != EVP_EncryptInit_ex(ctx,EVP_aes_128_cbc(),NULL,key,"[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]\")){
(error message)
}
if(1 != EVP_EncryptUpdate(ctx,output,&len,input,strlen(input))){
(error message)
}
if(1 != EVP_EncryptFinal_ex(ctx, output+len, &len)){
(error message)
}
EVP_CIPHER_CTX_free(ctx)
/*This prints out 0 when I change cbc to gcm, but prints a correct size when I use cbc*/
printf("Output size: %d \n", len);
/*Properly writes to file when cbc used but not when gcm used. Nothing is in encrypted.bin when gcm is used when encrypted text should be there.*/
binfile = fopen("encrypted.bin","wb");
fwrite(outbuf,len,1,binfile);
当我将 EVP_aes_128_cbc() 更改为 EVP_aes_128_gcm() 时,代码不再有效。我还将 iv 更改为长度 12 ("[=22=][=22=][=22=][=22=][=22=][=22=][=22=][=22=][=22=][=22=][=22=][=22=]")。最后,我在 EVP_EncryptFinal_ex:
之后添加了这个代码块 char tag[] = "1234567890123456";
if(1 != EVP_CIPHER_CTX_ctrl(ctx,EVP_CTRL_GCM_GET_TAG,16,tag)){
(error message)
}
打印时我的最终输出大小为 0,里面什么也没有(在原始代码中注明)。我的问题是,当我只将 cbc 更改为 gcm 时,为什么我没有得到任何加密?是因为 key/iv 大小问题还是更大?
EncryptUpdate 和 EncryptFinal 都添加到输出缓冲区(或不添加)。 碰巧,对于您的短明文消息,在 CBC 模式下,所有输出均由 EncryptFinal 写入,而对于 GCM 模式,所有输出均由 EncryptUpdate 写入。
您代码中的问题在于,您在 EncryptUpdate 和 EncryptFinal 中重复使用了 "len" 变量。他们都(覆盖)写入 len 由调用添加的数据量。因此,在 CBC 模式下,EncryptFinal 会用 16 覆盖初始值 0,而在 GCM 模式下,初始值 13 会被 0 覆盖。
您应该按照 openssl wiki (https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption) 中的说明进行操作:
/* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertext_len = len;
/* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
handleErrors();
ciphertext_len += len;
顺便说一句:如果只是文本,您可以继续使用 strlen 作为输入数据的长度,但请记住,这不会加密零终止符,因此您必须在解密后手动添加它。