大数库openssl实现RSA加密(C语言)

大数库openssl实现RSA加密(C语言)

学习记录
使用大数库openssl中的大数运算函数实现RSA加密
这是第一次借用大数库来辅助编程,是一次宝贵的经历,记录一下。
我是直接使用下载好的openssl的文件,将其放入vs2019的工程中就可以使用大数库的函数了
下载地址:https://download.csdn.net/download/weixin_47627174/14503343.
文件截图:

如何将文件放到编译器里(vs2019为例)
1.新建工程,新建添加c文件,右键项目的属性,VC++目录
将包含目录编辑为openssl的include文件,库目录编辑为openssl的lib文件

2.链接器
将附加库目录编辑为openssl的lib和bin文件


3.引用代码

#pragma comment(lib, "libeay32.lib" )
#pragma comment(lib, "ssleay32.lib")

之后使用头文件引用即可

#include</openssl/include/xxx.h>

(建议把openssl文件直接放到D盘根目录比较方便)
4.报错
提示:OPENSSL_Uplink(100F2010,05):no OPENSSL_Applink
解决方法:

extern "C"
{
#include</openssl/include/applink.c>
}

或者

#ifdef  __cplusplus
extern "C" {
#endif
#include</openssl/include/applink.c>
#ifdef  __cplusplus
}

RSA加密
RSA公钥算法由Rivest、Shamir、Adleman于1978年提出的,是目前公钥密码的国际标准。算法的数学基础是Euler定理,是基于Deffie-Hellman的单项陷门函数的定义而给出的第一个公钥密码的实际实现,其安全性建立在大整数因子分解的困难性之上。
RSA算法的明文空间M=密文空间C=Zn整数
1.生成密钥

2.加密算法

3.解密算法

有关的BN函数
1.初始化函数

函数解释举例
BIGNUM *BN_new(void)生成一个BIGNUM结构并返回指针BIGNUM *a = BN_new();
void BN_free(BIGNUM *a)释放一个BIGNUM结构,释放完后a=NULLBN_free(a);

2.上下文结构

函数解释举例
BN_CTX *BN_CTX_new(void)申请一个新的上下文结构BN_CTX *ctx = BN_CTX_new();

3.字符串转换

函数解释举例
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)将s中的len位的正整数转化为大数,储存在retBN_bin2bn(str, length,M);
char *BN_bn2hex(const BIGNUM *a)将大数转化为十六进制的字符串返回BN_bn2hex(a);

4.计算有关函数

函数解释举例
int BN_one(BIGNUM *a)设置a为1BN_one (a);
int BN_is_one(BIGNUM *a)判断a是不是1if (BN_is_one (a))
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)计算a与b的差,值储存在r中, r = a - b;如果成功返回1,否则返回0BN_sub(r, a, b);
int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)计算a与b的积,值储存在r中 r = a * b,如果成功返回1,否则返回0BN_mul (r, a, b, ctx)
int BN_gcd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)计算a与b的最大公约数,值储存在r中, r = gcd(a,b),如果成功返回1,否则返回0BN_gcd (r, a, b, ctx);
BIGNUM *BN_mod_inverse(BIGNUM *r, BIGNUM *a, const BIGNUM *n)取a对n取模的逆元存在r中, ((r * a) % n) == 1BN_mod_inverse(d, e, fn, ctx)
nt BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m)大数的模指数运算(利用经典模运算实现)r ← a^p modmBN_mod_exp_simple(M, C, d, n, ctx);

5.随机函数

函数解释举例
BIGNUM *BN_generate_prime(BIGNUM *ret, int num, int safe, BIGNUM *add, BIGNUM *rem, void (*callback)(int, int, void *), void *cb_arg);伪随机生成num位素数,如果ret返回值不为null,则用来储存答案,后面参数不需要的话可以填nullBN_generate_prime(p, bits, NULL,NULL, NULL, NULL,NULL);
int BN_rand_range(BIGNUM *rnd, BIGNUM *range)产生的0<rnd<rangeBN_rand_range(e, fn)

程序代码

#include <stdio.h>
#include</openssl/include/bn.h> //引用大数库中的BN函数
#pragma comment(lib, "libeay32.lib" )  //引用
#pragma comment(lib, "ssleay32.lib")
#ifdef  __cplusplus
extern "C" {
#endif
#include</openssl/include/applink.c>
#ifdef  __cplusplus
}
#endif
int zhuanhuan(int a)//将十六进制转换为十进制
{
	if (a< 60)
	{
		a= a- '0';
	}
	if (a> 64)
	{
		a = a- 'A' + 10;
	}
	return a;
}
void main() 
{
		BIGNUM* p=BN_new();    //大素数p
		BIGNUM* q = BN_new();  //大素数q
		BIGNUM* n= BN_new();    //n=p*q
		BIGNUM* fn = BN_new();   //fn=(p-1)*(q-1)
		BIGNUM* d = BN_new();    //d=e-1 mod (n)
		BIGNUM * e = BN_new();   //整数e,1<e<fn且gcd(fn, e)=1
		BIGNUM* r = BN_new();   
		BIGNUM* M = BN_new();    //明文
		BIGNUM* C = BN_new();    //密文
		BIGNUM* one = BN_new();  //将one设置为1
		BN_one(one);
		int length;
		char str[100] = "0";    
		char* show;     
		int bits = 512;     //512bits
		int i,j,t;   
		int sum=0; 
		printf("请输入要加密的的明文:");
		scanf_s("%s",str,sizeof(str));
		length = strlen(str);                //记录明文的长度
	    BN_bin2bn(str, length,M);            //将明文以十六进制转换为大数
		printf("明文:%s\n", str);    
		BN_generate_prime(p, bits, NULL,NULL, NULL, NULL,NULL);       //生成512bits的大素数p
		BN_generate_prime(q, bits, NULL, NULL, NULL, NULL, NULL);     //生成512bits的大素数q
		BN_CTX* ctx = BN_CTX_new();         //上下文结构		
		BN_mul(n ,p, q, ctx);            //n=p*q
		BN_sub(p, p, one);       
		BN_sub(q, q, one);
		BN_mul(fn, p, q, ctx);           //fn=(p-1)*(q-1)
		do
		{
		BN_rand_range(e, fn); //产生的0 < e < fn的随机数
	    BN_gcd(r, e, fn, ctx); //r = e, fn最大公约数
		} while (!BN_is_one(r)); //判断r是否等于1
		BN_mod_inverse(d, e, fn, ctx);    //模逆运算
		//公钥加密 C = M^e mod n
		BN_mod_exp_simple(C, M, e, n , ctx);
		show = BN_bn2hex(C);     //将密文转换为十六进制
		printf("密文:%s\n", show);
		//私钥解密 M = C^d mod n。
		BN_mod_exp_simple(M, C, d, n, ctx);
		show = BN_bn2hex(M);
		//printf("%x",show);//测试
		printf("\n解密后的明文:%s", show);  //将解密后的明文转换为十六进制
		printf("\n解密后的明文:");

		for (i = 0; i < length; i++)  //将解密后的明文转化为对应的ASCII的字符
		{
			j = *(show + 2*i);   //每两位为一个整体
			t= *(show +2* i+1);
			j=zhuanhuan(j);
			t=zhuanhuan(t);
			sum = j * 16 + t;
			printf("%c", sum); //将ASCII的字符输出
		}
		//释放结构
		BN_CTX_free(ctx);
		BN_free(p);
		BN_free(q);
		BN_free(n);
		BN_free(fn);
		BN_free(d);
		BN_free(e);
		BN_free(r);
		BN_free(M);
		BN_free(C);
}

程序运行结果:

结语:编写程序仍有许多不足,如果其中有任何错误,望能指出,十分感谢!
参考:
https://blog.csdn.net/jnxxhzz/article/details/81235981
https://blog.csdn.net/samsho2/article/details/87902775

  • 7
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值