RSA加密/解密
Posted
技术标签:
【中文标题】RSA加密/解密【英文标题】:RSA encrypt/decrypt 【发布时间】:2012-03-13 11:48:12 【问题描述】:我正在编写一个 C 程序来加密(基于私钥)和解密(基于公钥)文本。我正在尝试使用 OpenSSL 库来做到这一点。有谁知道任何好的教程、快速入门指南或示例代码?我在网上没有找到任何像样的。
【问题讨论】:
您应该从加密入门开始。您通常使用公钥加密并使用私钥解密。 【参考方案1】:这是我创建的一个示例,用于使用 RSA 加密文件,不对称算法使用 RSA,对称算法使用 AES-128-CBC,使用 OpenSSL EVP 函数:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <arpa/inet.h> /* For htonl() */
int do_evp_seal(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file)
int retval = 0;
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_CIPHER_CTX ctx;
unsigned char buffer[4096];
unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH];
size_t len;
int len_out;
unsigned char *ek = NULL;
int eklen;
uint32_t eklen_n;
unsigned char iv[EVP_MAX_IV_LENGTH];
if (!PEM_read_RSA_PUBKEY(rsa_pkey_file, &rsa_pkey, NULL, NULL))
fprintf(stderr, "Error loading RSA Public Key File.\n");
ERR_print_errors_fp(stderr);
retval = 2;
goto out;
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
retval = 3;
goto out;
EVP_CIPHER_CTX_init(&ctx);
ek = malloc(EVP_PKEY_size(pkey));
if (!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &pkey, 1))
fprintf(stderr, "EVP_SealInit: failed.\n");
retval = 3;
goto out_free;
/* First we write out the encrypted key length, then the encrypted key,
* then the iv (the IV length is fixed by the cipher we have chosen).
*/
eklen_n = htonl(eklen);
if (fwrite(&eklen_n, sizeof eklen_n, 1, out_file) != 1)
perror("output file");
retval = 5;
goto out_free;
if (fwrite(ek, eklen, 1, out_file) != 1)
perror("output file");
retval = 5;
goto out_free;
if (fwrite(iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), 1, out_file) != 1)
perror("output file");
retval = 5;
goto out_free;
/* Now we process the input file and write the encrypted data to the
* output file. */
while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0)
if (!EVP_SealUpdate(&ctx, buffer_out, &len_out, buffer, len))
fprintf(stderr, "EVP_SealUpdate: failed.\n");
retval = 3;
goto out_free;
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
perror("output file");
retval = 5;
goto out_free;
if (ferror(in_file))
perror("input file");
retval = 4;
goto out_free;
if (!EVP_SealFinal(&ctx, buffer_out, &len_out))
fprintf(stderr, "EVP_SealFinal: failed.\n");
retval = 3;
goto out_free;
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
perror("output file");
retval = 5;
goto out_free;
out_free:
EVP_PKEY_free(pkey);
free(ek);
out:
return retval;
int main(int argc, char *argv[])
FILE *rsa_pkey_file;
int rv;
if (argc < 2)
fprintf(stderr, "Usage: %s <PEM RSA Public Key File>\n", argv[0]);
exit(1);
rsa_pkey_file = fopen(argv[1], "rb");
if (!rsa_pkey_file)
perror(argv[1]);
fprintf(stderr, "Error loading PEM RSA Public Key File.\n");
exit(2);
rv = do_evp_seal(rsa_pkey_file, stdin, stdout);
fclose(rsa_pkey_file);
return rv;
以及对应的解密例子:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <arpa/inet.h> /* For htonl() */
int do_evp_unseal(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file)
int retval = 0;
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_CIPHER_CTX ctx;
unsigned char buffer[4096];
unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH];
size_t len;
int len_out;
unsigned char *ek;
unsigned int eklen;
uint32_t eklen_n;
unsigned char iv[EVP_MAX_IV_LENGTH];
if (!PEM_read_RSAPrivateKey(rsa_pkey_file, &rsa_pkey, NULL, NULL))
fprintf(stderr, "Error loading RSA Private Key File.\n");
ERR_print_errors_fp(stderr);
retval = 2;
goto out;
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
retval = 3;
goto out;
EVP_CIPHER_CTX_init(&ctx);
ek = malloc(EVP_PKEY_size(pkey));
/* First need to fetch the encrypted key length, encrypted key and IV */
if (fread(&eklen_n, sizeof eklen_n, 1, in_file) != 1)
perror("input file");
retval = 4;
goto out_free;
eklen = ntohl(eklen_n);
if (eklen > EVP_PKEY_size(pkey))
fprintf(stderr, "Bad encrypted key length (%u > %d)\n", eklen,
EVP_PKEY_size(pkey));
retval = 4;
goto out_free;
if (fread(ek, eklen, 1, in_file) != 1)
perror("input file");
retval = 4;
goto out_free;
if (fread(iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), 1, in_file) != 1)
perror("input file");
retval = 4;
goto out_free;
if (!EVP_OpenInit(&ctx, EVP_aes_128_cbc(), ek, eklen, iv, pkey))
fprintf(stderr, "EVP_OpenInit: failed.\n");
retval = 3;
goto out_free;
while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0)
if (!EVP_OpenUpdate(&ctx, buffer_out, &len_out, buffer, len))
fprintf(stderr, "EVP_OpenUpdate: failed.\n");
retval = 3;
goto out_free;
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
perror("output file");
retval = 5;
goto out_free;
if (ferror(in_file))
perror("input file");
retval = 4;
goto out_free;
if (!EVP_OpenFinal(&ctx, buffer_out, &len_out))
fprintf(stderr, "EVP_SealFinal: failed.\n");
retval = 3;
goto out_free;
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
perror("output file");
retval = 5;
goto out_free;
out_free:
EVP_PKEY_free(pkey);
free(ek);
out:
return retval;
int main(int argc, char *argv[])
FILE *rsa_pkey_file;
int rv;
if (argc < 2)
fprintf(stderr, "Usage: %s <PEM RSA Private Key File>\n", argv[0]);
exit(1);
rsa_pkey_file = fopen(argv[1], "rb");
if (!rsa_pkey_file)
perror(argv[1]);
fprintf(stderr, "Error loading PEM RSA Private Key File.\n");
exit(2);
rv = do_evp_unseal(rsa_pkey_file, stdin, stdout);
fclose(rsa_pkey_file);
return rv;
我认为这很容易理解。正如所写的那样,这两个命令都可以用作管道的一部分(它们在stdin
上接受输入并将输出写入stdout
)。
【讨论】:
我不明白你们为什么将对称加密算法 aes 带入非对称公钥加密系统 RSA?这是否正确? @scarface:由于各种原因,非对称密钥系统不用于加密批量数据 - 它们用于加密对称密钥系统的密钥,对称密钥系统本身用于加密批量数据。这正是 EVP*“信封加密”功能的工作原理。 是你的代码吗?你能放任何关于openssl的链接来下载吗?谢谢以上是关于RSA加密/解密的主要内容,如果未能解决你的问题,请参考以下文章