1. RSA算法
明文长度不能超过密钥长度。如果密钥是1024位,那么明文长度只能是1024/8-11=128-11=117字符。
生成密文的长度等于密钥长度。如果密钥是1024位,那么生成的密文长度1024/8=128字符。也就是说,RSA算法加密生成的密文长度是固定的。
密钥长度越大,生成密文的长度也就越大,加密的速度也就越慢。通常不会使用RSA算法加密整个报文,一般只用于生成签名或者加密其它算法的密钥。
2. RSA公钥加密C代码
公钥文件,以BEGIN RSA PUBLIC KEY和以BEGIN PUBLIC KEY开头是不一样的。BEGIN RSA PUBLIC KEY对应PKCS#1格式,BEGIN PUBLIC KEY对应PKCS#8格式。两者使用的获取函数也不一样。
以BEGIN RSA PUBLIC KEY开头,使用PEM_read_RSAPublicKey函数。
以BEGIN PUBLIC KEY开头,使用PEM_read_RSA_PUBKEY函数。
下面展示了两种读取RSA公钥文件的方法,最终加密函数都是RSA_public_encrypt()。
方法一是使用PEM_read_RSA_PUBKEY()函数读取公钥文件;
方法二是使用BIO_read_filename()和PEM_read_bio_RSA_PUBKEY()函数读取公钥文件。
#include <stdio.h>
#include <string.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
/*
* 通过公钥文件进行加密
* 方法一:使用PEM_read_RSA_PUBKEY函数
*/
int rsa_pub_encrypt_file1(char* keyFile, char* data)
{
RSA *rsa = NULL;
FILE *fp = NULL;
int nReturn = 0;
int rsaL = 0;
int len = 0;
char *encData = NULL;
fp = fopen(keyFile, "r");
if (NULL == fp){
printf("open file error\n");
nReturn = -1;
goto _exit;
}
// rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);
rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); //根据不同的开头选择不同的函数
if (NULL == rsa){
printf("PEM_read_RSA_PUBKEY error\n");
nReturn = -1;
goto _exit;
}
rsaL = RSA_size(rsa);
encData = (char*)malloc(rsaL+1); //密文长度等于密钥长度,C语言需考虑结束符
memset(encData, 0x00, rsaL+1);
len = RSA_public_encrypt(strlen(data), (unsigned char*)data, (unsigned char*)encData, rsa, RSA_PKCS1_PADDING);
if (len == -1){
printf("RSA_public_encrypt error\n");
nReturn = -1;
goto _exit;
}
// 加密结果不能直接打印,会乱码,通常会将RSA加密结果做BASE64转码。
int n1 = 0;
char tmpBuf64[1024+1];
memset(tmpBuf64, 0x00, sizeof(tmpBuf64));
printf("RSA_public_encrypt return len = %d\n", len);
n1 = base64_encode(encData, len, tmpBuf64);
printf("The result of RSA public encrypt and base64 encode is [%d]\n", n1);
printf("[%s]\n", tmpBuf64);
_exit:
if (encData != NULL){
free(encData);
encData = NULL;
}
if (fp != NULL){
close(fp);
fp = NULL;
}
if (rsa != NULL){
RSA_free(rsa);
rsa = NULL;
}
return nReturn;
}
/*
* 通过公钥文件进行加密
* 方法二:使用BIO_read_filename()函数
*/
int rsa_pub_encrypt_file2(char* keyFile, char* data)
{
int nReturn = 0;
BIO *key = NULL;
RSA *rsa = NULL;
int len = 0;
char *encData = NULL;
key = BIO_new(BIO_s_file());
BIO_read_filename(key, keyFile);
// rsa = PEM_read_bio_RSAPublicKey(key, NULL, NULL, NULL);
rsa = PEM_read_bio_RSA_PUBKEY(key, NULL, NULL, NULL); //根据不同的开头选择不同的函数
if (NULL == rsa)
{
printf("PEM_read_bio_RSA_PUBKEY error\n");
nReturn = -1;
goto _exit;
}
len = RSA_size(rsa);
encData = (char*)malloc(len+1);
memset(encData, 0x00, sizeof(encData));
len = RSA_public_encrypt(strlen(data), (unsigned char*)data, (unsigned char*)encData, rsa, RSA_PKCS1_PADDING);
if (len == -1){
printf("RSA_public_encrypt error\n");
nReturn = -1;
goto _exit;
}
// 加密结果不能直接打印,会乱码,通常会将RSA加密结果做BASE64转码。
int n1 = 0;
char tmpBuf64[1024+1];
memset(tmpBuf64, 0x00, sizeof(tmpBuf64));
printf("RSA_public_encrypt return len = %d\n", len);
n1 = base64_encode(encData, len, tmpBuf64);
printf("The result of RSA public encrypt and base64 encode is [%d]\n", n1);
printf("[%s]\n", tmpBuf64);
_exit:
if (key != NULL){
BIO_free_all(key);
key = NULL;
}
if (encData != NULL){
free(encData);
encData = NULL;
}
if (rsa != NULL){
RSA_free(rsa);
rsa = NULL;
}
return nReturn;
}
3. RSA私钥解密C代码
私钥只有PKCS#8标准。
下面展示了两种读取RSA私钥文件的方法,最终解密函数都是RSA_private_decrypt()。
方法一是使用PEM_read_RSAPrivateKey()函数读取私钥文件;
方法二是使用BIO_read_filename()和PEM_read_bio_RSAPrivateKey()函数读取私钥文件。
#include <stdio.h>
#include <string.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
/*
* 通过私钥文件进行解密
* 方法一:PEM_read_RSAPrivateKey读取私钥文件
*/
int rsa_private_decrypt_file1(char* keyFile, char* buf64)
{
RSA *rsa = NULL;
FILE *fp = NULL;
int nReturn = 0;
int len = 0;
char tmpBuf[1024+1];
char decData[1024+1];
memset(tmpBuf, 0x00, sizeof(tmpBuf));
memset(decData, 0x00, sizeof(decData));
/* base64解码 */
len = base64_decode(buf64, tmpBuf);
printf("base64_decode return len = %d\n", len);
/* rsa解码 */
fp = fopen(keyFile, "r");
if (NULL == fp)
{
printf("open file error\n");
nReturn = -1;
goto _exit;
}
rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
if (len == -1){
printf("PEM_read_RSAPrivateKey error\n");
nReturn = -1;
goto _exit;
}
int n1 = RSA_private_decrypt(len, (unsigned char*)tmpBuf, (unsigned char*)decData, rsa, RSA_PKCS1_PADDING);
if (n1 == -1)
{
printf("RSA_private_decrypt error\n");
nReturn = -1;
goto _exit;
}
printf("the result len [%d]\n", n1);
printf("the result [%s]\n", decData);
_exit:
if (fp != NULL){
close(fp);
fp = NULL;
}
if (rsa != NULL){
RSA_free(rsa);
rsa = NULL;
}
return nReturn;
}
/*
* 通过私钥文件进行解密
* 方法二:BIO_read_filename和PEM_read_bio_RSAPrivateKey读取私钥文件
*/
int rsa_private_decrypt_file2(char* keyFile, char* buf64)
{
RSA *rsa = NULL;
BIO *key = NULL;
int nReturn = 0;
int len = 0;
char tmpBuf[1024+1];
char decData[1024+1];
memset(tmpBuf, 0x00, sizeof(tmpBuf));
memset(decData, 0x00, sizeof(decData));
/* base64解码 */
len = base64_decode(buf64, tmpBuf);
printf("base64_decode return len = %d\n", len);
/* rsa解码 */
key = BIO_new(BIO_s_file());
BIO_read_filename(key, keyFile);
rsa = PEM_read_bio_RSAPrivateKey(key, NULL, NULL, NULL);
int n1 = RSA_private_decrypt(len, (unsigned char*)tmpBuf, (unsigned char*)decData, rsa, RSA_PKCS1_PADDING);
if (n1 == -1)
{
printf("RSA_private_decrypt error\n");
nReturn = -1;
goto _exit;
}
printf("the result len [%d]\n", n1);
printf("the result [%s]\n", decData);
_exit:
if (key != NULL){
BIO_free_all(key);
key = NULL;
}
if (rsa != NULL){
RSA_free(rsa);
rsa = NULL;
}
return nReturn;
}