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;
}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐