RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。本文介绍如何使用openssl命令和C代码实现基础的RSA加/解密和签名/验签功能。
一、openssl命令实现RSA加解密
1、生成私钥和公钥
- 生成私钥
openssl genrsa -out private.key 2048 #生成私钥
- 使用私钥生成公钥
openssl rsa -pubout -in private.key -out public.key #私钥生成公钥
2、签名、验签
- 使用private.key私钥签名data.txt,生成data.sign
openssl rsautl -sign -inkey private.key -keyform PEM -in data.txt -out data.sign #签名
- 使用公钥验签verify.key
openssl rsautl -verify -inkey public.key -pubin -in data.sign #验签
注意:执行生成密钥对和验签命令时,一定要注意文件名后面是否有空格符或tab符,否则会出现"No such file or directory"的报错
可以看到验签后,打印信息与签名前的文件内容相同,签名、验签测试OK。
3、加密、解密
- 使用公钥加密 data.txt 生成 data.encrypt
openssl rsautl -encrypt -pubin -inkey public.key -in data.txt -out data.encrypt
注意:每次用公钥加密生成的加密文件内容都会变化
- 使用私钥解密 data.encrypt
openssl rsautl -decrypt -inkey private.key -in data.encrypt
如果要存到文件,解密命令后面加 "-out data.decrypt"
4、其他openssl命令
- 从certificate.crt证书提取公钥到public_key.pem
openssl x509 -pubkey -noout -in certificate.crt > public_key.pem
- 直接使用证书验签(从证书获取公钥,使用公钥验签)
openssl rsautl -verify -inkey certificate.crt -certin -in data.sign
二、C语言实现RSA非对称加解密
下面使用的密钥对openssl命令生成的 private.key 和 public.key
1、签名、验签
1.1 C代码实现
代码下载链接:https://download.youkuaiyun.com/download/hinewcc/89484338
- openssl_rsa.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>
#include "openssl_rsa.h"
void rsa_init(void)
{
printf("rsa init ... \n");
OpenSSL_add_all_algorithms();
}
/*
*****************************************************************************************
* 函 数 名: rsa_sign
* 功能说明: RSA使用私钥签名
* 形 参: key : 私钥
* file_in : 输入需要签名的文件
* file_out : 签名后生成的文件
* 返 回 值: 0:成功, 其他:失败
*****************************************************************************************
*/
int rsa_sign(const char *key, const char *file_in, const char *file_out)
{
int ret = -1;
int keysize = 0;
RSA *rsa = NULL;
BIO *in = NULL, *out = NULL;
unsigned char *rsa_in = NULL, *rsa_out = NULL;
int rsa_inlen = 0, rsa_outlen = 0, len = 0;
/* 从私钥提取 RSA */
FILE *fp = fopen(key, "r");
if (NULL == fp) {
perror("Open Key Error: \n");
return -1;
}
rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL,NULL);
if (!rsa) {
perror("EVP_PKEY_get1_RSA Error: \n");
goto error;
}
/* 打开file_in文件内容,创建file_out文件 */
in = BIO_new_file(file_in, "rb");
if (NULL == in) {
printf("BIO_new_file: open source file fail\n");
goto error;
}
out = BIO_new_fil