我是密码学新手,所以我决定创build一个简单的程序,打开一个文件encryption数据,把它放在etest.txt中,然后打开这个文件解密它,并把它indetest.txt.I知道这听起来真的很受欢迎,但它的为教育目的。 所以这里是我的代码。 我已经阅读了许多有关这个问题的主题,但是他们都没有为我工作。
#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
对不起,如果我的问题听起来很愚蠢。 希望你能帮忙。 谢谢。
这里有一些错误。 首先,当你正在阅读和加密:
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,如果是这样,则跳出循环:
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) {
请注意,我们正在保存RSA_public_encrypt
的返回值。 在这里,你正在把加密的数据写入磁盘:
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; }
看到这个帖子关于使用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)
加密块。 因此,从磁盘中读取很多字节,并将这些字节传递给函数。 另外,检查fread
的返回值,如果没有获得预期的数量,则检查并返回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; }
通过应用这些修复程序,您应该可以获得预期的结果。