【问题标题】:openssl EVP fails randomly in decryptionopenssl EVP 在解密中随机失败
【发布时间】:2015-02-05 15:13:28
【问题描述】:

当我尝试使用相同的值多次运行相同的程序时,我在使用openssl/evp.h
EVP_OpenFinalEVP_OpenInit 的更高级别包络解密时遇到问题。我在过去 5 天里一直在努力,但没有运气。我在这里写我的完整代码。请帮帮我。如果有人可以尝试重现错误并让我知道我错在哪里,那就太好了。

错误信息:

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
4944:error:0606506D:lib(6):func(101):reason(109):.\crypto\evp\evp_enc.c:460:

这是代码

#include <iostream>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <stdio.h>

void handleErrors(void);
int envelope_seal(EVP_PKEY **pub_key, unsigned char *plaintext, int plaintext_len,
                  unsigned char **encrypted_key, int *encrypted_key_len, unsigned char *iv,
                  unsigned char *ciphertext);
int envelope_open(EVP_PKEY *priv_key, unsigned char *ciphertext, int ciphertext_len,
                  unsigned char *encrypted_key, int encrypted_key_len, unsigned char *iv,
                  unsigned char *plaintext);

using namespace std;

int main()
{
    RSA *rsa_pubkey= RSA_new();
    RSA *rsa_prikey= RSA_new();
    EVP_PKEY *evp_pubkey = EVP_PKEY_new();
    EVP_PKEY *evp_prikey = EVP_PKEY_new();
    FILE *rsa_prikey_file = NULL;
    FILE *rsa_pubkey_file = NULL;
    rsa_pubkey_file = fopen("pubkey.pem", "r");
    if (!rsa_pubkey_file)
    {
        fprintf(stderr, "Error loading PEM RSA Public Key File.\n");
        exit(2);
    }

    PEM_read_RSA_PUBKEY(rsa_pubkey_file, &rsa_pubkey,NULL, NULL);

    EVP_PKEY_assign_RSA(evp_pubkey,rsa_pubkey);

    rsa_prikey_file = fopen("key.pem", "r");
    if (!rsa_prikey_file)
    {
        fprintf(stderr, "Error loading PEM RSA private Key File.\n");
        exit(2);
    }
    PEM_read_RSAPrivateKey(rsa_prikey_file, &rsa_prikey,NULL, NULL);

    EVP_PKEY_assign_RSA(evp_prikey,rsa_prikey);


    unsigned char *plaintext = (unsigned char*) "The quick brown fox jumps over thes lazy dog";
    unsigned char ciphertext[256] = {};
    unsigned char plaintextt[256] = {};
    int ciphertextlength;
    unsigned char *encKey  = (unsigned char*)malloc(RSA_size(rsa_pubkey));
    unsigned char iv[16] = {};


    envelope_seal(&evp_pubkey, plaintext,strlen((const char*)plaintext),&encKey, &ciphertextlength,iv,ciphertext);

    envelope_open(evp_prikey, ciphertext, strlen((const char*)ciphertext), encKey, strlen((const char*)encKey),iv,plaintextt);

    std::cout <<"Result: "<<plaintextt<<std::endl;

    EVP_PKEY_free(evp_pubkey);
    EVP_PKEY_free(evp_prikey);
    free(ciphertext);
    free(encKey);

}

int envelope_seal(EVP_PKEY **pub_key, unsigned char *plaintext, int plaintext_len,
                  unsigned char **encrypted_key, int *encrypted_key_len, unsigned char *iv,
                  unsigned char *ciphertext)
{
    EVP_CIPHER_CTX *ctx;

    int ciphertext_len;

    int len;

    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

    if(1 != EVP_SealInit(ctx, EVP_aes_128_cbc(),
                         encrypted_key,
                         encrypted_key_len,
                         iv,
                         pub_key, 1))
    {
        handleErrors();
    }

    if(1 != EVP_SealUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
    {
        handleErrors();
    }
    ciphertext_len = len;

    if(1 != EVP_SealFinal(ctx, ciphertext + len, &len))
    {
        handleErrors();
    }
    ciphertext_len += len;

    EVP_CIPHER_CTX_free(ctx);

    return ciphertext_len;
}



int envelope_open(EVP_PKEY *priv_key, unsigned char *ciphertext, int ciphertext_len,
                  unsigned char *encrypted_key, int encrypted_key_len, unsigned char *iv,
                  unsigned char *plaintext)
{
    EVP_CIPHER_CTX *ctx;

    int len;

    int plaintext_len;

    if(!(ctx = EVP_CIPHER_CTX_new()))
    {
        handleErrors();
    }

    if(1 != EVP_OpenInit(ctx, EVP_aes_128_cbc(), encrypted_key,
                         encrypted_key_len, iv, priv_key))
    {
        handleErrors();
    }

    if(1 != EVP_OpenUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
    {
        handleErrors();
    }
    plaintext_len = len;

    if(1 != EVP_OpenFinal(ctx, plaintext + len, &len))
    {
        handleErrors();
    }
    plaintext_len += len;

    EVP_CIPHER_CTX_free(ctx);
    plaintext[plaintext_len] = '\0';

    return plaintext_len;
}


void handleErrors(void)
{
    perror("Error: ");
    ERR_print_errors_fp(stderr);
    abort();
}

【问题讨论】:

  • EVP_OpenInit() 在错误时返回 0,如果成功则返回非零整数(实际上是恢复的密钥大小)。
  • 好的,但为什么相同数据会随机失败?
  • 您忽略了返回值。从PEM_read_RSA_PUBKEYPEM_read_RSAPrivateKey 等函数开始检查故障。并致电RSA_check_key 验证您正在加载的密钥。
  • 我相信 strlen((const char*)ciphertext) 是您的问题之一。你可能还有其他人。

标签: c++ c encryption openssl


【解决方案1】:

envelope_seal()返回加密字符串的长度,我必须把这个长度放在envelope_open()

int **length** = envelope_seal(&evp_pubkey, plaintext,strlen((const char*)plaintext),&encKey, &ciphertextlength,iv,ciphertext);
envelope_open(evp_prikey, ciphertext, **length**, encKey, strlen((const char*)encKey),iv,plaintextt);

【讨论】:

    【解决方案2】:

    随机崩溃是由envelope_sealenvelope_open 之前的长度计算引起的。长度应如下所示:

    unsigned char *plaintext = (unsigned char*) "The quick brown fox jumps over thes lazy dog";
    int ciphertextlength;
    unsigned int enclen = EVP_PKEY_size(evp_prikey);
    unsigned char *encKey  = (unsigned char*)malloc(enclen);
    unsigned char *ciphertext = (unsigned char*)malloc(enclen);
    unsigned char plaintextt[enclen] = {};
    unsigned char iv[16] = {};
    
    
    unsigned int length = envelope_seal(&evp_pubkey, plaintext,strlen((const char*)plaintext),&encKey, &ciphertextlength,iv,ciphertext);
    envelope_open(evp_prikey, ciphertext, length, encKey, enclen,iv,plaintextt);
    

    正如您的回答所说,envelope_seal 返回大小。您无法获得char* 的大小,因为当您的plaintext 的大小小于48 时,总是会发生崩溃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-20
      • 2019-11-19
      • 1970-01-01
      • 2021-03-17
      • 2020-10-14
      • 2021-01-30
      • 2019-04-22
      • 1970-01-01
      相关资源
      最近更新 更多