我遇到一个问题,即使用EVP_SealInit,EVP_SealUpdate和EVP_SealFinal的加密过程正在运行,并且没有返回任何失败代码。
尝试解密消息通过EVP_OpenInit和EVP_OpenUpdate工作,但是EVP_OpenFinal失败返回0.尽管函数返回0,但完全解密的文本存储在输出缓冲区中,并且从EVP_OpenFinal返回的总输出长度与总数相同从EVP_SealFinal返回的长度。
我引用了这篇SO帖子:OpenSSL RSA: Unable to encrypt/decrypt messages longer than 16 bytes
我相信OP修改了他的代码并修复了,所以我无法在那里得到很多帮助。值得注意的是,无论消息长度如何,我的问题都存在。在EVP_OpenFinal调用期间,10,15和140个char消息都失败,但每条消息都完全存储在输出缓冲区中。
加密:
int envelope_seal(EVP_PKEY *pub_key, uint8_t const *plaintext,
int plaintext_len, uint8_t *encrypted_key,
int *encrypted_key_len, uint8_t *iv,
uint8_t *ciphertext)
{
EVP_CIPHER_CTX *ctx = NULL;
int ciphertext_len = 0;
int len = 0;
if (!(ctx = EVP_CIPHER_CTX_new()))
{
handleErrors();
return -1;
}
if (!EVP_SealInit(ctx, EVP_aes_256_gcm(), &encrypted_key,
encrypted_key_len, iv, &pub_key, 1))
{
handleErrors();
return -1;
}
if (!EVP_SealUpdate(ctx, ciphertext + len, &len, plaintext, plaintext_len))
{
handleErrors();
return -1;
}
ciphertext_len += len;
if (!EVP_SealFinal(ctx, ciphertext + ciphertext_len, &len))
{
handleErrors();
return -1;
}
ciphertext_len += len;
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
解密:
int envelope_open(EVP_PKEY *priv_key, uint8_t const *ciphertext,
int ciphertext_len, uint8_t const *encrypted_key, int encrypted_key_len, uint8_t const *iv, uint8_t *plaintext)
{
EVP_CIPHER_CTX *ctx = NULL;
int plaintext_len = 0;
int len = 0;
if (!(ctx = EVP_CIPHER_CTX_new()))
{
handleErrors();
return -1;
}
if (!EVP_OpenInit(ctx, EVP_aes_256_gcm(), encrypted_key,
encrypted_key_len, iv, priv_key))
{
handleErrors();
return -1;
}
if (!EVP_OpenUpdate(ctx, plaintext + plaintext_len, &len, ciphertext, ciphertext_len))
{
handleErrors();
return -1;
}
plaintext_len += len;
if (!EVP_OpenFinal(ctx, plaintext + plaintext_len, &len))
{
handleErrors();
return -1;
}
plaintext_len += len;
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
错误处理:
void handleErrors(void)
{
ERR_print_errors_fp(stderr);
}
如果有人能突出OpenUpdate和OpenFinal之间的内部差异,任何帮助突出我可能会忽略的内容都会很棒。
谢谢!
答案 0 :(得分:1)
AES_GCM和AES_CCM支持对数据执行经过身份验证的加密和解密的功能,这是通过在加密数据上创建MAC标签来实现的。 MAC标签可确保数据在传输和存储过程中不会被意外更改或恶意篡改。
加密操作的输出将是密文和一个标记。在解密操作期间应使用该标签,以确保密文没有被篡改。
有关更多信息,请参考https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption。
using EVP_aes_128_gcm in openssl for aad with size of not multiple of 16带有tag和aad实现,在这里错过了,并导致解密失败。
在调用EVP_SealFinal()之后,我们需要检索加密期间使用的标签。
unsigned char tag[32]={0};
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
{
fprintf(stderr, "EVP_CTRL_GCM_GET_TAG failed\n");
exit(1);
}
我们需要传递在加密过程中获得的相同标签,然后再调用EVP_OpenFinal
if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
{
fprintf(stderr, "EVP_CTRL_GCM_SET_TAG failed\n");
exit(1);
}