2015-02-05 102 views
0

我在使用更高級別的信封解密弗朗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

回答

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

隨機碰撞是由你的長度計算造成的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*的尺寸,因爲您的碰撞總是發生。