RSA加密解密算法原理以及实现_rsa简介及源码实现(2),BAT等大厂必问技术面试题

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注网络安全)
img

正文

5、计算出e对于

φ

(

n

)

\varphi(n)

φ(n)的模反元素d

de mod

φ

(

n

)

\varphi(n)

φ(n) =1

在这里解释下什么是模反元素。

如果两个正整数e和

φ

(

n

)

\varphi(n)

φ(n)互质,那么一定可以找到一个整数d,使得ed-1被

φ

(

n

)

\varphi(n)

φ(n)整除,或者说ed除以

φ

(

n

)

\varphi(n)

φ(n)所得的余数为1,此时,d就叫做e的模反元素。
也就是说在e和

φ

(

n

)

\varphi(n)

φ(n)已知的情况下,d只要满足ed-1=k

φ

(

n

)

\varphi(n)

φ(n),k为任意整数,d便是e的模反元素。同时也可得到,e的模反元素d并不是唯一的。
例如,e=3,

φ

(

n

)

=

11

\varphi(n)=11

φ(n)=11,则d=4

±

\pm

±k·11。

至此,公钥,私钥便都已经得到。

6、将e、n公开作为公钥进行加密

假设明文为M,密文为C,则加密过程为

M

e

m

o

d

n

=

C

M^e mod n =C

Memodn=C

7、将d,n作为私钥进行解密

C

d

m

o

d

n

=

M

C^d mod n =M

Cdmodn=M

RSA私钥解密的证明详解

二、RSA算法使用c++语言实现时遇到的问题以及解决方案

1.问题1:模反元素的求解

在第5步中,我们需要计算出e对于

φ

(

n

)

\varphi(n)

φ(n)的模反元素d。
如果使用暴力法求解,那么时间复杂度势必为O(n),这对于一个很大的整数来说,势必需要很长的时间去运行,效率低下,因此需要用一种更快的算法去优化该过程。
解决办法:在第四步中,我们随机产生一个整数e, e的范围是1 < e < φ(n), 并且e与 φ(n) 互质.互质的两个数的最大公约数为1,我们便可以用欧几里得算法去判断是否互质。

欧几里得算法可以用公式表示为gcd(a,b)=gcd(b,a mod b),利用辗转相除的思路。设F(x,y)表示为x,y的最大公约数,取k=x/y,b=x%y,那么x=ky+b,如果一个数能够整除x和y,那么一定可以整除y和b,也就是说,能够整除y和b的数,一定能够整除x和y,所以x和y的公约数和y和b的公约数相同,其最大公约数也相同,则有F(x,y)=F(y,x%y)(x>=y>0),这样就把求两个数的最大公约数转化为求两个更小的数的公约数,直到其中一个数为0,那么另一个数就是两者的最大公约数。

举个例子:

F(42,30)=F(30,12)=F(12,6)=F(6,0)=6

但对于以上过过程,我们如何用代码去实现,我们先从公约数的特点入手。

设x=

k

1

x

1

k_1x_1

k1​x1​,y=

k

1

y

1

k_1y_1

k1​y1​,则F(x,y)=

k

1

k_1

k1​ F(x1,y1)。
设x=p

x

1

x_1

x1​,(p为素数且y%p!=0)则F(x,y)=F(x1,y)。
现在取p=2。
若x,y均为偶数,则F(x,y)=2F(x/2,y/2)。
若x为偶数,y为奇数则F(x,y)=F(x/2,y)。
若x为奇数,y为偶数则F(x,y)=F(x,y/2)。
若x和y同时为奇数,F(x,y)=F(y,x-y)。(两个奇数相减后必定会出现一个偶数)
这种做法的算法复杂度为O(log2(max(x,y)))。

#include<iostream>
#include<algorithm>
#include<string.h> 
using namespace std;
int isoushu(long x)
{
	if(x%2==0)  return 1;
	else return 0;
}
 int fun(long long a,long long b)
{   if(b>a)  return fun(b,a);
	else if(a==0)return b;

	
	else 
	{  if(isoushu(a))
	      if(isoushu(b))
	   {
	   	return (fun(a>>1,b>>1)<<1);
	   }
	   else return fun(a>>1,b);
	   
	   else 
	   {    if(isoushu(b))
	   	return  fun(a,b>>1);
	   	 else return (a-b,b);
	   	 
	   }
	
	
	}
}
main()
{
	long long a,b;
	cin>>a>>b;
    cout<<fun(a,b);

}


问题2:大数的幂运算

  1. 在计算机计算大数的指数的过程中, 计算的数字不断增大, 非常的占用我们的计算资源
  2. 我们计算的中间过程数字大的恐怖, 我们现有的计算机是没有办法记录这么长的数据的, 会导致溢出.

解决方案:在程序设计过程中,经常要去求一些大数对于某个数的余数,为了得到更快、计算范围更大的算法,产生了快速幂取模算法
从一个最简单的例子入手:求a^b % c = ?

int ans=1;
for(int i=1;i<=b;i++)
{
    ans=ans\*a;
}
ans=ans%c;

该程序实现存在很大的问题,首先算法时间度为O(n),其次如果a和b过大,很容易就会溢出。
如何进行改进?这里就要用到中学时学到的同余定理:积的取余等于取余的积的取余。

a

b

a^b

ab% c = (a * a * a a) % c
= ((a % c) * (a % c) * (a % c) (a % c)) % c
= (a % c)

b

^b

b% c

此时我们可以从上述公式中想到既然某个因子取余之后相乘再取余余数保持不变,那么可以通过改良程序得到以下版本。

int ans=1;
a=a%c;//加上这一句
for(int i=1;i<=b;i++)
{
    ans=(ans\*a)%c;//取余
}
ans=ans%c;

但是这个算法在时间复杂度上没有改进,仍为O(b),不过已经好很多的,但是在c过大的条件下,还是很有可能超时,所以,我们需要用到快速幂算法来进行改进。

关于快速幂的算法的介绍,我么从推导其公式入手。

首先我们将十进制的指数b转换为2进制的形式

在这里插入图片描述

其中

a

n

a_n

an​代表对应对应第n位的二进制值,非0即1。那么由二进制转换为十进制的公式我们可以得到

在这里插入图片描述
在这里插入图片描述
化简上述公式可得
在这里插入图片描述

a

b

a^b

abmod c可重写为

在这里插入图片描述

此处的

a

i

a_i

ai​要么为0,要么为1,如果

a

i

a_i

ai​为0,那么这一项值就为1。所以可以再次将上述式子化简为

在这里插入图片描述
其中

k

i

k_i

ki​表示

a

i

a_i

ai​不为0的项。

同时发现,对于每一项的计算时,计算后一项的结果时用前一项的结果的平方取余。用公式表示为

在这里插入图片描述

形如上式的公式推导,我们将其用代码实现。

int ans=1;
a=a%c;
while(b>0)
{
    if(b%2==1)
        ans=(ans\*a)%c;
        b=b/2;
        a=(a\*a)%c;
}

此时,当b=0时,所有的因子都已经相乘,算法结束。于是便可以在O(log b)的时间内完成了。所以在进行模幂运算时, 运算的复杂度已经和指数b的大小没有直接关系了, 有直接关系的是b的二进制bit位数。


问题3:大数的加/减/乘/除/模运算

在RSA算法中的数字极大, 是我们现有计算机无法直接计算的, 所以需要我们手动实现大数的加减乘除. 所以在实现中,直接调用boost库中的大数运算库cppp_int。

boost中的cpp_int库的介绍文档
https://www.boost.org/doc/libs/1_58_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/cpp_int.html
项目使用的是boost_1_83_0版本的大数库,下载链接https://www.boost.org/users/download/
在VS中还需要将解压好的boost库路径添加到附加目录, 步骤如下
在这里插入图片描述
在这里插入图片描述

问题4:大数产生随机数

我们平时用的随机数函数是 srand()设置随机数种子, 一般传入time(0), 用 rand()获取随机数, 随机数 = rand % num; 随机数范围是 [0, num). 在不同平台的不同编译器下rand()函数所能获取的随机数的范围不同, 但由于目前CPU位数的限制, 顶多也就是个64位的数字, 所以我们还需要能产生大随机数的方法.

解决方案:在boost库的random库中 有着大数随机数的获取方法,在调用时包含头文件#include<boost/multiprecision/random.hpp>

问题5:大数产生质数

大数的素性检测有专门的算法, 比如fermat检测, Miller-Rabin等算法. 在boost库中的实现了Miller-Rabin素性检测算法,使用时添加头文件#include <boost/multiprecision/miller_rabin.hpp>

三、RSA加密算法代码实现

rsa.h

#pragma once
#include<iostream>
#include<boost/multiprecision/cpp\_int.hpp>//大数库
#include<boost/multiprecision/random.hpp>//随机数库
#include<boost/multiprecision/miller\_rabin.hpp>//素性检测
#include<boost/algorithm/string.hpp> //spilt()接口就在这个库中
 
namespace br = boost::random;
namespace bm = boost::multiprecision;
 
#define NUMBER 128 //临时缓冲区大小
#define SECRET\_KEY\_PATH "secret\_key.txt" //存储N,D,E的文件名
#define SIZE 128 //控制随机数大小, 范围是 0 ~ 1 << SIZE
 
typedef struct {
	bm::int1024\_t m_ekey;//公钥e
	bm::int1024\_t m_dkey;//私钥d
	bm::int1024\_t m_nkey;//公共模数n
}Key;
 
class RSA {
	Key m_key;
	bm::int1024\_t GetPrime();
	bool isPrime(bm::int1024\_t& num);
	bm::int1024\_t getNkey(bm::int1024\_t& prime1, bm::int1024\_t& prime2);//获取公共模数n
	bm::int1024\_t getOrla(bm::int1024\_t& prime1, bm::int1024\_t& prime2);//欧拉函数, 得到f(n)
	bm::int1024\_t getEkey(bm::int1024\_t& orla);//获取公钥
	bm::int1024\_t getDkey(bm::int1024\_t& ekey, bm::int1024\_t& orla);//获取私钥
	void exGcd(bm::int1024\_t a, bm::int1024\_t b, bm::int1024\_t\* x, bm::int1024\_t\* y);//求模反元素
	bm::int1024\_t getGcd(bm::int1024\_t num1, bm::int1024\_t num2);//最大公约数
	bm::int1024\_t \_encrypt(bm::int1024\_t data, bm::int1024\_t ekey, bm::int1024\_t nkey);//加密,需要加密数据和公钥(e, n)
	bm::int1024\_t \_decrypt(bm::int1024\_t data, bm::int1024\_t dkey, bm::int1024\_t nkey);//解密,需要要解密的数据和私钥(d, n)
	void getKeys();
public:
	RSA();
	bool encrypt(const std::string filename, const std::string outname);//加密
	bool decrypt(const std::string filename, const std::string outname);//解密
};

rsa.cpp

#include<fstream>
#include<vector>
#include"rsa.h"
using namespace std;
 
RSA::RSA() {
	getKeys();
}
bm::int1024\_t RSA::getNkey(bm::int1024\_t& prime1, bm::int1024\_t& prime2) {
	return prime1 \* prime2;
}
bm::int1024\_t RSA::getOrla(bm::int1024\_t& prime1, bm::int1024\_t& prime2) {//prime1和prime2必须互质
	return (prime1 - 1) \* (prime2 - 1);
}
bm::int1024\_t RSA::getEkey(bm::int1024\_t& orla) {
	bm::int1024\_t ekey;
	br::mt11213b gen((size\_t)time(0));
	br::uniform_int_distribution<bm::int1024\_t> dist(bm::int1024\_t(0), (bm::int1024\_t(orla)));
	do {
		ekey = dist(gen);
	} while (ekey < 2 || getGcd(ekey, orla) != 1);
	return ekey;
}
bm::int1024\_t RSA::getDkey(bm::int1024\_t& ekey, bm::int1024\_t& orla) {
	bm::int1024\_t x, y;
	exGcd(ekey, orla, &x, &y);
	return (x % orla + orla) % orla;//变换, 让解密密钥是一个比较小的数
}
bm::int1024\_t RSA::getGcd(bm::int1024\_t num1, bm::int1024\_t num2) {
	bm::int1024\_t num;
	while ((num = num1 % num2)) {
		num1 = num2;



还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!


王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。


对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!


【完整版领取方式在文末!!】


***93道网络安全面试题***


![](https://img-blog.csdnimg.cn/img_convert/6679c89ccd849f9504c48bb02882ef8d.png)








![](https://img-blog.csdnimg.cn/img_convert/07ce1a919614bde78921fb2f8ddf0c2f.png)





![](https://img-blog.csdnimg.cn/img_convert/44238619c3ba2d672b5b8dc4a529b01d.png)





内容实在太多,不一一截图了


### 黑客学习资源推荐


最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!


对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

#### 1️⃣零基础入门


##### ① 学习路线


对于从来没有接触过网络安全的同学,我们帮你准备了详细的**学习成长路线图**。可以说是**最科学最系统的学习路线**,大家跟着这个大的方向学习准没问题。


![image](https://img-blog.csdnimg.cn/img_convert/acb3c4714e29498573a58a3c79c775da.gif#pic_center)


##### ② 路线对应学习视频


同时每个成长路线对应的板块都有配套的视频提供:


![image-20231025112050764](https://img-blog.csdnimg.cn/874ad4fd3dbe4f6bb3bff17885655014.png#pic_center)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)**
![img](https://img-blog.csdnimg.cn/img_convert/7ae7f430c91d428fda60f5abe491c1fb.png)

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**





![](https://img-blog.csdnimg.cn/img_convert/07ce1a919614bde78921fb2f8ddf0c2f.png)





![](https://img-blog.csdnimg.cn/img_convert/44238619c3ba2d672b5b8dc4a529b01d.png)





内容实在太多,不一一截图了


### 黑客学习资源推荐


最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!


对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

#### 1️⃣零基础入门


##### ① 学习路线


对于从来没有接触过网络安全的同学,我们帮你准备了详细的**学习成长路线图**。可以说是**最科学最系统的学习路线**,大家跟着这个大的方向学习准没问题。


![image](https://img-blog.csdnimg.cn/img_convert/acb3c4714e29498573a58a3c79c775da.gif#pic_center)


##### ② 路线对应学习视频


同时每个成长路线对应的板块都有配套的视频提供:


![image-20231025112050764](https://img-blog.csdnimg.cn/874ad4fd3dbe4f6bb3bff17885655014.png#pic_center)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)**
[外链图片转存中...(img-hcAOafcv-1713172441385)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值