2015-12-02 222 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

相关问题