gpt4 book ai didi

c - OpenSSL RSA : Unable to encrypt/decrypt messages longer than 16 bytes

转载 作者:太空狗 更新时间:2023-10-29 17:12:00 24 4
gpt4 key购买 nike

我正在开发一个使用 OpenSSL 进行基本 RSA 加密和解密的简单程序。它对于小消息(<16 字节)工作正常,但对于任何超过它的东西都失败了。我知道公钥加密的一个局限性是你不能加密任何超过 key 大小的东西。在我的例子中,我使用的是 1024 位 key ,所以我应该使用 128 字节(可能由于填充而略少),对吗?如果是这样,那不是我遇到的情况。

这是我的程序的 15 字节输出:

Generating RSA keypair...done.
Message to encrypt: 0123456789ABCDE
16 bytes encrypted
Decrypted message: 0123456789ABCDE

还有 16 个字节:

Generating RSA keypair...done.
Message to encrypt: 0123456789ABCDEF
16 bytes encrypted
140153837057696:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:467:
Decrypted message: (null)

看来不管怎么说,总共只有16个字节被加密了。

我的加密函数(已修复更新):

unsigned char* rsa_seal(EVP_PKEY *pub_key, unsigned char *msg, size_t **enc_msg_len, unsigned char **sym_key, int *sym_key_len, unsigned char **iv) {
size_t msg_len = strlen((char*)msg);
unsigned char *encrypt = malloc(EVP_PKEY_size(pub_key));

EVP_CIPHER_CTX *ctx = malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(ctx);

*sym_key = malloc(EVP_PKEY_size(pub_key));
*iv = malloc(EVP_MAX_IV_LENGTH);

**enc_msg_len = 0;

if(!EVP_SealInit(ctx, EVP_aes_128_cbc(), sym_key, sym_key_len, *iv, &pub_key, 1)) {
ERR_print_errors_fp(stderr);
encrypt = NULL;
goto return_free;
}

if(!EVP_SealUpdate(ctx, encrypt, (int*)*enc_msg_len, msg, (int)msg_len)) {
ERR_print_errors_fp(stderr);
encrypt = NULL;
goto return_free;
}

if(!EVP_SealFinal(ctx, encrypt, (int*)*enc_msg_len)) {
ERR_print_errors_fp(stderr);
encrypt = NULL;
goto return_free;
}

return_free:
EVP_CIPHER_CTX_cleanup(ctx);
free(ctx);
ctx = NULL;

return encrypt;
}

对应的解密函数(已修复更新):

char* rsa_open(EVP_PKEY *pri_key, unsigned char *enc_msg, size_t *enc_msg_len, unsigned char *sym_key, int sym_key_len, unsigned char *iv) {
size_t dec_len = 0;
unsigned char *decrypt = malloc((*enc_msg_len) + EVP_MAX_IV_LENGTH);
if(decrypt == NULL) return NULL;

EVP_CIPHER_CTX *ctx = malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(ctx);

if(!EVP_OpenInit(ctx, EVP_aes_128_cbc(), sym_key, sym_key_len, iv, pri_key)) {
ERR_print_errors_fp(stderr);
decrypt = NULL;
goto return_free;
}

if(!EVP_OpenUpdate(ctx, decrypt, (int*)&dec_len, enc_msg, (int)*enc_msg_len)) {
ERR_print_errors_fp(stderr);
decrypt = NULL;
goto return_free;
}

if(!EVP_OpenFinal(ctx, decrypt, (int*)&dec_len)) {
ERR_print_errors_fp(stderr);
decrypt = NULL;
goto return_free;
}

decrypt[dec_len] = '\0';

return_free:
EVP_CIPHER_CTX_cleanup(ctx);
free(ctx);
ctx = NULL;

return (char*)decrypt;
}

key 生成函数:

int rsa_init(EVP_PKEY **rsa_keypair) {
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);

if(!EVP_PKEY_keygen_init(ctx)) {
ERR_print_errors_fp(stderr);
return -1;
}

if(!EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KEY_LENGTH)) {
ERR_print_errors_fp(stderr);
return -1;
}

if(!EVP_PKEY_keygen(ctx, rsa_keypair)) {
ERR_print_errors_fp(stderr);
return -1;
}

EVP_PKEY_CTX_free(ctx);

return 0;
}

最后,我的主要内容:

int main() {
EVP_PKEY *rsa_keypair = NULL; // RSA keypair
char msg[BUFFER]; // Message to encrypt
unsigned char *encrypt = NULL; // Encrypted message
char *decrypt = NULL; // Decrypted message

// Generate key pair
printf("Generating RSA keypair...");
if(rsa_init(&rsa_keypair) == -1) {
fprintf(stderr, "\nError generating RSA keypair.\n");
exit(1);
}
printf("done.\n");

// Get the message to encrypt
printf("Message to encrypt: ");
fgets(msg, BUFFER-1, stdin);
msg[strlen(msg)-1] = '\0';

// Load error strings in anticipation of error
ERR_load_crypto_strings();

// Encrypt the message
size_t *encrypt_len = malloc(sizeof(size_t));
unsigned char *sym_key = NULL;
unsigned char *iv = NULL;
int sym_key_len;
encrypt = rsa_seal(rsa_keypair, (unsigned char*)msg, &encrypt_len, &sym_key, &sym_key_len, &iv);
printf("%d bytes encrypted\n", (int)*encrypt_len);

// Decrypt it
decrypt = rsa_open(rsa_keypair, (unsigned char*)encrypt, (size_t*)encrypt_len, sym_key, sym_key_len, iv);
printf("Decrypted message: %s\n", decrypt);

free(encrypt);
free(decrypt);
free(encrypt_len);
free(sym_key);
free(iv);
EVP_PKEY_free(rsa_keypair);

return 0;
}

非常感谢任何帮助!谢谢。

编辑:正如下面的数学所指出的,似乎我的错误的答案隐藏在 OpenSSL 中:https://www.openssl.org/docs/crypto/EVP_EncryptInit.html#

最佳答案

这是因为您没有正确处理 EVP_SealUpdate()EVP_SealFinal()outl 参数>、EVP_OpenUpdate()EVP_OpenFinal()

每个 EVP_XxxxUpdate()EVP_XxxxFinal() 调用都会对输出缓冲区产生影响。因此,您需要通过对返回的每个 outl 求和并每次提供预期的缓冲区(缓冲区开始 + 已处理的字节)来跟踪密封/打开过程。

unsigned char* rsa_seal(...)
{
...
**enc_msg_len = 0;

EVP_SealUpdate(ctx, encrypt + **enc_msg_len, &outl, msg, (int)msg_len);
**enc_msg_len += outl;

EVP_SealFinal(ctx, encrypt + **enc_msg_len, &outl);
**enc_msg_len += outl;
...
}

char* rsa_open(...)
{
...
dec_len = 0;

EVP_OpenUpdate(ctx, decrypt + dec_len, &outl, enc_msg, (int)*enc_msg_len);
dec_len += outl;

EVP_OpenFinal(ctx, decrypt + dec_len, &outl);
dec_len += outl;
...
}

程序使用 15 字节缓冲区,因为在那种情况下,EVP_XxxxUpdate() 调用在 outl 中返回 0(没有足够的数据来密封/打开一个 block ),将问题隐藏在您的代码逻辑中。

注意:数据未使用 RSA key 直接加密,而是使用生成的对称 key (在您的情况下为 AES-128)加密。这就是 block 大小为 16 字节的原因。

关于c - OpenSSL RSA : Unable to encrypt/decrypt messages longer than 16 bytes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10727133/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com