OpenSSL的EVP随机失败解密

问题描述:

我在使用更高级别的信封解密弗朗openssl/evp.h
EVP_OpenFinalEVP_OpenInit失败随机一个问题,当我试图多次使用相同的值运行同一程序。我正在为此工作5天,但没有运气。我在这里写完整的代码。请帮助我。如果有人能够重现错误,并且让我知道我错在哪里,这将是非常好的。OpenSSL的EVP随机失败解密

错误消息:

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(); 
} 
+0

EVP_OpenInit()在错误时返回0,如果成功则返回非零整数(实际上是恢复的密钥大小)。 – 2015-02-05 15:19:57

+0

好的,但为什么随机失败与相同的数据? – Kahn 2015-02-05 15:21:47

+0

你忽略了返回值。从“PEM_read_RSA_PUBKEY”和“PEM_read_RSAPrivateKey”等函数开始检查失败。并调用'RSA_check_key'来验证您正在加载的密钥。 – jww 2015-02-08 08:57:09

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); 

随机碰撞是由你的长度计算造成的b在envelope_seal和​​之前。长度应该看起来像:

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返回大小。当您的plaintext的尺寸小于48时,您无法获得char*的尺寸,因为您的碰撞总是发生。