2015-12-02 224 views
2

我是新的密碼學,所以我決定創建一個簡單的程序,將打開一個文件加密數據,將其放入etest.txt,然後打開這個文件解密它,並把它indetest.txt.I知道這聽起來真的很受歡迎,但它的教育目的。這裏是我的代碼。我已經閱讀了許多關於這個問題的主題,但沒有一個工作。我C:OpenSSL RSA_private_decrypt()失敗,出現「錯誤:0407A079:rsa例程:RSA_padding_check_PKCS1_OAEP:oaep解碼錯誤」

#include <openssl/rsa.h> 
#include <openssl/pem.h> 
#include <openssl/err.h> 
#include <stdio.h> 
#include <string.h> 

int main(void) { 
    size_t pri_len;   // Length of private key 
    size_t pub_len;   // Length of public key 
    char *pri_key;   // Private key 
    char *pub_key;   // Public key 
    char *msg = malloc(256); // Message to encrypt 
    char *encrypt = NULL; // Encrypted message 
    char *decrypt = NULL; // Decrypted message 
    char *err;    // Buffer for any error messages 
    size_t red; 

    RSA *keypair = RSA_generate_key(2048, 3, NULL, NULL); 
    FILE *in = fopen("test.txt", "r"); 
    FILE *out = fopen("etest.txt", "w"); 

    if(in == NULL) 
    { 
     printf("in Error is %d (%s).\n", errno, strerror(errno)); 
    } 
    if(out == NULL) 
    { 
     printf("out Error is %d (%s).\n", errno, strerror(errno)); 
    } 

    encrypt = malloc(RSA_size(keypair)); 

    for(;;) 
    { 
     red = fread(msg, 1, RSA_size(keypair)-42, in); 
     if((RSA_public_encrypt(RSA_size(keypair)-42, (unsigned char*)msg, (unsigned char*)encrypt, 
              keypair, RSA_PKCS1_OAEP_PADDING)) == -1) { 
      ERR_load_crypto_strings(); 
      ERR_error_string(ERR_get_error(), err); 
      fprintf(stderr, "Error encrypting message: %s\n", err); 
     } 

     if(fwrite(encrypt, 1, strlen(encrypt), out) == 1) 
     { 
      printf("fwrite Error is %d (%s).\n", errno, strerror(errno)); 
     } 

     if(feof(in)) 
     { 
      break; 
     }  
    } 

    fclose(in); 
    fclose(out); 

    in = fopen("etest.txt", "r"); 
    out = fopen("dtest.txt", "w"); 

    if(in == NULL) 
    {   
     printf("in Error is %d (%s).\n", errno, strerror(errno)); 
    } 

    if(out == NULL) 
    {   
     printf("out Error is %d (%s).\n", errno, strerror(errno)); 
    } 

    decrypt = malloc(RSA_size(keypair)); 

    for(;;) 
    { 
     red = fread(msg, 1, 256, in); 
     if(RSA_private_decrypt(red, (unsigned char*)msg, (unsigned char*)decrypt, 
           keypair, RSA_PKCS1_OAEP_PADDING) == -1) { 

      ERR_load_crypto_strings(); 
      ERR_error_string(ERR_get_error(), err); 
      fprintf(stderr, "Error decrypting message: %s\n", err); 
     }   

     fwrite(decrypt, 1, strlen(decrypt), out); 

     if(feof(in)) 
     { 
      break; 
     } 
    } 
    fclose(in); 
    fclose(out);  
    RSA_free(keypair); 
    return 0; 
} 

當我運行代碼,它給我回錯誤說:。Error decrypting message: error:0407A079:rsa routines:RSA_padding_check_PKCS1_OAEP:oaep decoding error很抱歉,如果我的問題聽起來很傻希望你能幫助謝謝

+0

你的問題是什麼? – fuz

+1

它給我回錯誤。爲什麼呢? – Ojs

回答

1

這裏有一些錯誤。首先,當你閱讀和加密:

red = fread(msg, 1, RSA_size(keypair)-42, in); 
if((RSA_public_encrypt(RSA_size(keypair)-42, (unsigned char*)msg, (unsigned char*)encrypt, 
            keypair, RSA_PKCS1_OAEP_PADDING)) == -1) { 

fread的呼叫不一定會讀取請求的字節數,並可能返回0。所以,當你到達文件的末尾,你的男人是加密比您需要的更多的字節。因此請通過red獲取要加密的字節數。另外,首先檢查red爲0,如果是break圈外的:我們正在拯救的RSA_public_encrypt返回值

red = fread(msg, 1, RSA_size(keypair)-42, in); 
if (red == 0) break; 
if(((red=RSA_public_encrypt(RSA_size(keypair)-42, (unsigned char*)msg, (unsigned char*)encrypt, 
            keypair, RSA_PKCS1_OAEP_PADDING))) == -1) { 

注意。那進場這兒,你要加密的數據寫入磁盤:

if(fwrite(encrypt, 1, strlen(encrypt), out) == 1) 

encrypt是一個字符數組,而不是字符串。這意味着它不是NULL終止的,它可能包含NULL字節。所以你不能使用strlen。相反,捕捉RSA_public_encrypt返回值和傳遞,作爲大小寫:

if(fwrite(encrypt, 1, red, out) == 1) 

因爲我們正在檢查的fread返回值來跳出循環,這是沒有必要:

if(feof(in)) 
{ 
    break; 
} 

請參閱this post關於使用feof的危險。

再有就是這個,當你讀回加密的數據:

red = fread(msg, 1, 256, in); 
if(RSA_private_decrypt(red, (unsigned char*)msg, (unsigned char*)decrypt, 
         keypair, RSA_PKCS1_OAEP_PADDING) == -1) { 

RSA_private_decrypt需要一個單獨的加密塊長度爲RSA_size(keypair)。所以從磁盤中讀取這麼多字節並將這些字節傳遞給函數。此外,檢查的freadbreak出來的返回值,如果你沒有得到預期的量,並捕獲的RSA_private_decrypt返回值:

red = fread(msg, 1, RSA_size(keypair), in); 
if (red < RSA_size(keypair)) break; 
if((red=RSA_private_decrypt(red, (unsigned char*)msg, (unsigned char*)decrypt, 
         keypair, RSA_PKCS1_OAEP_PADDING)) == -1) { 

後來,當你寫解密的數據到磁盤:

fwrite(decrypt, 1, strlen(decrypt), out); 

雖然發生了什麼解密可能是一個字符串(如果你輸入的文件是純文本),返回的數據不爲NULL終止,所以比許多字節而不是使用strlen明確寫入:

fwrite(decrypt, 1, red, out); 

最後,作爲與加密循環,這是沒有必要在解密循環:

if(feof(in)) 
{ 
    break; 
} 

有了這些修補程序應用,你應該得到預期的結果。

+0

非常感謝你。如果你能回答我還有其他問題。我可以用這個加密任何類型的文件嗎?我的意思是如果我使用example.jpg而不是test.txt它會起作用嗎? – Ojs

+1

@Ojs是的,這將適用於任何文件,無論內容如何。這就是爲什麼不把數據視爲字符串的重要性。 – dbush

+0

還有一個請:)這個算法有多安全? – Ojs

相關問題