linux环境C语言RSA加解密

9 篇文章 0 订阅

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

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是用C语言实现RSA加解密算法的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <math.h> #include <stdint.h> // 定义大质数素数数组,数组长度为100 uint32_t PrimeList[100] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541 }; // 定义欧拉函数,参数为两个质数 uint32_t Euler(uint32_t p, uint32_t q) { return (p - 1) * (q - 1); } // 定义取模反元素函数 uint32_t ModInverse(uint32_t a, uint32_t b) { uint32_t r, r1 = a, r2 = b; uint32_t t, t1 = 0, t2 = 1; while (r2 > 0) { t = r1 / r2; r = r1 - t * r2; r1 = r2; r2 = r; t = t1 - t * t2; t1 = t2; t2 = t; } if (r1 == 1) { if (t1 < 0) { t1 += a; } return t1; } else { return 0; } } // 定义素数判断函数 int IsPrime(uint32_t n) { int i; if (n < 2) { return 0; } for (i = 0; i < 100; i++) { if (n == PrimeList[i]) { return 1; } if (n % PrimeList[i] == 0) { return 0; } } for (i = 251; i <= sqrt(n); i += 2) { if (n % i == 0) { return 0; } } return 1; } // 定义随机生成素数函数 uint32_t RandomPrime() { uint32_t p; do { p = rand() % 65536 + 32768; } while (!IsPrime(p)); return p; } // 定义生成RSA密钥对函数 void RSAKeyGen(uint32_t *p, uint32_t *q, uint32_t *n, uint32_t *e, uint32_t *d) { srand((unsigned)time(NULL)); *p = RandomPrime(); *q = RandomPrime(); *n = *p * *q; uint32_t phi = Euler(*p, *q); do { *e = rand() % phi; } while (*e < 2 || *e >= phi || phi % *e == 0); *d = ModInverse(phi, *e); } // 定义RSA加密函数 uint32_t RSAEncrypt(uint32_t m, uint32_t e, uint32_t n) { uint32_t c = 1; for (int i = 0; i < e; i++) { c = (c * m) % n; } return c; } // 定义RSA解密函数 uint32_t RSADecrypt(uint32_t c, uint32_t d, uint32_t n) { uint32_t m = 1; for (int i = 0; i < d; i++) { m = (m * c) % n; } return m; } int main() { uint32_t p, q, n, e, d; RSAKeyGen(&p, &q, &n, &e, &d); printf("p = %u, q = %u, n = %u, e = %u, d = %u\n", p, q, n, e, d); uint32_t m = 12345; printf("m = %u\n", m); uint32_t c = RSAEncrypt(m, e, n); printf("c = %u\n", c); uint32_t m2 = RSADecrypt(c, d, n); printf("m2 = %u\n", m2); return 0; } ``` 这段代码包括随机生成素数、生成RSA密钥对、RSA加密RSA解密等多个函数。通过调用这些函数,可以实现RSA加解密算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值