Openssl EVP "EVP_CTRL_GCM_GET_TAG" 失败
Openssl EVP "EVP_CTRL_GCM_GET_TAG" fails
我在 C++ 中使用 Openssl EVP。不知何故获取标签失败。
我的代码:
int do_crypt(FILE *in, FILE *out){
unsigned char inbuf[1024], aadbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
int inlen, lenbuf, unused, outlen;
EVP_CIPHER_CTX *ctx;
unsigned char key[] = "0123456789abcdeF";
unsigned char iv[] = "123456788765";
unsigned char tag[16];
ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);
EVP_CipherInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL, do_encrypt);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, sizeof(iv), NULL);
OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 12);
EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1);
FILE * aad_f = fopen("aad.txt", "rb");
for(;;){
size_t a = fread(aadbuf, 1, 1024, aad_f);
lenbuf = int(a);
if (lenbuf <= 0) break;
EVP_CipherUpdate(ctx, NULL, &unused, aadbuf, lenbuf);
}
/* Input text */
for(;;){
size_t a = fread(inbuf, 1, 1024, in);
inlen = int(a);
if (inlen <= 0) break;
EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen);
fwrite(outbuf, 1, outlen, out);
}
EVP_CipherFinal_ex(ctx, outbuf, &outlen);
EVP_CIPHER_CTX_free(ctx);
fwrite(outbuf, 1, outlen, out);
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag)){
cout << "error get tag" << endl;
return 0;
}
FILE * tag_f = fopen("tag.txt", "wb");
fwrite(tag, 1, sizeof(tag), tag_f);
cout << tag << endl;
}
return 0;
}
但是为什么呢?所有其他的 EVP functions 都做得很好。我想念什么?我必须调用其他功能吗? @\267* 而不是标签,被写入 tag.txt 文件。
代码中有两个错误:
- 由于
sizeof
用于判断IV的长度,因此0-终止符也被计算在内,并判断出错误的长度13。必须应用 strlen
而不是 sizeof
,其中 returns 是正确的值 12。
- 在确定标签之前释放上下文,即在
EVP_CIPHER_CTX_ctrl
之前调用EVP_CIPHER_CTX_free
。此顺序必须颠倒。
通过这些更改,将创建正确的密文和标签。
请注意,固定的 key/IV 对只能用于测试。实际上,key/IV 对只能使用一次,尤其是对于 GCM。
我在 C++ 中使用 Openssl EVP。不知何故获取标签失败。 我的代码:
int do_crypt(FILE *in, FILE *out){
unsigned char inbuf[1024], aadbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
int inlen, lenbuf, unused, outlen;
EVP_CIPHER_CTX *ctx;
unsigned char key[] = "0123456789abcdeF";
unsigned char iv[] = "123456788765";
unsigned char tag[16];
ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);
EVP_CipherInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL, do_encrypt);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, sizeof(iv), NULL);
OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 12);
EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1);
FILE * aad_f = fopen("aad.txt", "rb");
for(;;){
size_t a = fread(aadbuf, 1, 1024, aad_f);
lenbuf = int(a);
if (lenbuf <= 0) break;
EVP_CipherUpdate(ctx, NULL, &unused, aadbuf, lenbuf);
}
/* Input text */
for(;;){
size_t a = fread(inbuf, 1, 1024, in);
inlen = int(a);
if (inlen <= 0) break;
EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen);
fwrite(outbuf, 1, outlen, out);
}
EVP_CipherFinal_ex(ctx, outbuf, &outlen);
EVP_CIPHER_CTX_free(ctx);
fwrite(outbuf, 1, outlen, out);
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag)){
cout << "error get tag" << endl;
return 0;
}
FILE * tag_f = fopen("tag.txt", "wb");
fwrite(tag, 1, sizeof(tag), tag_f);
cout << tag << endl;
}
return 0;
}
但是为什么呢?所有其他的 EVP functions 都做得很好。我想念什么?我必须调用其他功能吗? @\267* 而不是标签,被写入 tag.txt 文件。
代码中有两个错误:
- 由于
sizeof
用于判断IV的长度,因此0-终止符也被计算在内,并判断出错误的长度13。必须应用strlen
而不是sizeof
,其中 returns 是正确的值 12。 - 在确定标签之前释放上下文,即在
EVP_CIPHER_CTX_ctrl
之前调用EVP_CIPHER_CTX_free
。此顺序必须颠倒。
通过这些更改,将创建正确的密文和标签。
请注意,固定的 key/IV 对只能用于测试。实际上,key/IV 对只能使用一次,尤其是对于 GCM。