【学习笔记】网络安全:如何快速理解RSA加密算法

1. 前言

网上关于RSA的文章已经有很多很多了,包括实现的代码等。
但很少有文章讲述如何快速理解并回答有关于RSA学习或考试的相关问题。
由于我近期在学习一门课程,是墨大的COMP90043 Cryptography and Security,其中有很多RSA相关的题目,在这里想简单总结一下答题心得,希望可以给有需要的人一些帮助吧。
 
 

2. RSA算法原理

RSA其实非常简单,其原理就是非对称加密,举个简单的例子:
小明想发个消息M给小亮,又怕别人偷看,小亮就生成2个密钥,一个公钥(public key)一个私钥(private key)。
小亮先将公钥发送给小明,小明收到公钥后用公钥将信息加密成C,加密过后的密文C返回给小亮,小亮接收到密文C后再利用私钥将信息解密为M’,也就是解密后的信息,M和M’必须是对等的。

小明 小亮 小明想发送消息给小亮 小亮生成了私钥和公钥 公钥 小明用公钥加密了信息 加密后的信息 小亮用私钥将密文解密 小明 小亮

是不是比课堂上老师讲得清楚很多?嘿嘿,主要是现在网课时期,加上我们墨大教密码学的Udaya教授的英文口音实在太重…导致这门课我上得十分痛苦 =-=
 

2.1. 具体算法实现步骤

一般作业首先会给我们两个质数(two primes),也叫素数。对于需要复习质数方面知识的,可以看这个视频,讲得非常清晰。
利用这两个质数pq获取密钥,我们需要做的其实就只有五个步骤:

  1. 获取质数pq
  2. p * q算出n
  3. 算出欧拉函数(Euler’s totient function),也就是:ϕ(n) = (p - 1) * (q - 1)
  4. 求出公钥e。这一步有一点复杂,也是所有文章中最含糊其辞的一个部分,我决定重点讲一下这个e。首先e需要大于1并且小于phi(n),也就是1 < e < ϕ*(n)。在这个条件下呢,e还必须和phi(n)互质(解释一下phi(n)就是ϕ(n))。在后面的例子中我也会谈到如何判断这两个数是不是互质。顺便一提,一般我们的作业题目都会说找一个最小的公钥(smallest possible exponent for the public key),即使作业没提到,正常情况下找最小公钥(Smallest (non-trivial) e)就好了,其他文章在这一步一般都会说:“随便找一个和phi(n)互质的e”,每次读到这里我人都傻了,在我印象数学不可能这么不严谨吧…
  5. 最后一步我们需要求出私钥d,这一步其实比求公钥还要复杂一些,教科书上说的是e × d1 mod ϕ(n)。说人话就是e * d 取余 ϕ(n) = 1。有了这些,我们就可以得出私钥d了。

拥有密钥后,加密信息就更简单了:
首先需要传输的消息一般是用大写M表示,加密后的密文是C,解密了的明文是M’,所以M == M’。因为你解密了肯定是你之前传输过来的消息。知道这些后我们来加解密消息:
加密:Me mod n = C
解密:Cd mod n = M’

 

2.2. 简单示例

好!大致逻辑讲完后,我找个例子示范一下:
借用我们第六周tutorial课件的第四题,首先我们假设两个质数43 and 47,并且我们要传递消息M = 313。

  1. p = 43; q = 47
  2. n = p x q = 2021
  3. ϕ(n) = (p - 1) x (q - 1) = 1932
  4. e = gcd(e, ϕ(n)) = gcd(e, 1932) = 5 (如果没看懂我后面的代码示例会给出解释)
  5. d = ed mod ϕ(n) = 1; = 5 x d mod 1932 = 1; d = 773 (同样没看懂我后面会解释)
    现在我们得出e = 5,d = 773, n = 2021,接下来我们开始加解密信息:
  6. C = Me mod n = 3135 % 2021 = 464
  7. M’ = Cd mod n = 464773 % 2021 = 313

大功告成。
关于获取公钥e私钥d的部分其实有一点复杂难懂,对于数学基础好的同学到这里可能就已经很清楚了。但如果像我一样数学不好,可能到这里还是有点一头雾水,那么接下来我们就用代码实操一下,因为关于获取公钥和私钥,使用代码会方便很多,并且也更容易帮助大家捋清思路,手算基本不太现实。
 

2.3. 代码示例

下面我会用python代码演示如何一步步得出结果,使用到的工具是jupyter。
(如果你不知道jupyter是什么,我十分推荐你去搜索相关的内容,jupyter可以将代码以块的形式运行,对于这种数学运算帮助非常大,你可以在过程中知道每一步的结果。当然,不使用jupyter甚至不使用python一样可以得出结果,所以问题不大。)
还是用上面的例子:

p = 43
q = 47
n = p * q
print(n)
# 输出结果为:2021
phin = (p - 1) * (q - 1)
print(phin)
# 输出结果为:1932

至此,我们拥有了p,q,n和phi(n)。
关于如何得出e,首先我们需要它和phi(n)互质,如何得知两个数是否互质,我们只需要知道他们的最大公约数(Greatest Common Divisor(GCD))等于1就好了。
在这里我会使用欧几里德算法得出e:

# gcd
def gcd(x,y):
    if x<y:
        x,y=y,x  # 翻转它们的位置,永远让第一个数大于第二个数。
    t = x%y		 # 先对两个数取一次余。
    while t!=0:	 # 一直对x和y取余,取到0为止。
        x,y=y,t
        t=x%y
    return y	 #返回上一次取余的结果,那个数就是它们的最大公约数。

# 使用gcd找出公钥e
def find_e(phin):
    i = 2	# e要大于1,小于phin,所以取2
    while True:
    	# 在i和1932之间找最大公约数,
    	# 如果最大公约数不是1就一直循环,利用这个伪死循环,计算机可以很快找出一个最小的公钥e
        if gcd(i, phin) == 1:
            break
        i+=1
    return i

e = find_e(phin)
print(e)
# 输出结果为:5

有代码和注释思路是不是就很清晰了。如果还是不太明白,我推荐你在用纸和笔模拟代码运行,自己去运算一次,反正输出的结果是5,你只需要计算4次能找到答案了。
 
计算d其实是比较复杂的,在这里我先给出一个gmpy2库的解决方案,非常优雅:

import gmpy2
d = gmpy2.invert(e,phin)
print(d)
# 输出结果为:773

就是这么简单,输出结果还非常快。当然,如果想要很好地去理解私钥d是如何产生的,我当时的思考方案是穷举法:

# calculate d
d = 1
while True:
	# 如果e*d mod phi(n) = 1,这个d就是我们要找的私钥, 没找到就一直循环下去。
    if e * d % phin == 1:
        break
    d+=1
    if d >= phin: # 如果d超出phi(n)的范围了,那么这个算式就是有问题的。
        print("out of the value")
        break
print(d)
# 输出结果为:773

其实一开始我对我这个方案挺满意的,直到某一次作业教授给出了一个将近100位数的phi(n)。我的电脑用上面这个代码跑了368分钟没跑出结果…最后我用gmpy2.invert,0.4秒就出结果了,真的裂开。
在这里插入图片描述
 
 
后面加密解密就很简单了:

m = 313 # 需要加密的明文
c = pow(m,e,n) # m^e mod n
print(c)
# 输出结果为:464

dm = pow(c,d,n) # c^d mod n
print(dm)
# 输出结果为:313

 
 

3. 结尾

本文中关于RSA加密算法其实只谈论了非常简单的基础知识,并且只是给出了一个解题的思路。但也基本属于胎教级教程了。RSA还是非常值得去深入研究的,包括签名验证等等。其实python有生成RSA密钥的库import rsa,感兴趣的可以自己去搜索一下相关的知识,我下面也附上了一个链接,在这里就不过多介绍了。
我也正在学习密码学相关的知识,谈论的比较浅薄,如果有什么地方写得不好或者有错误,欢迎指正。
 
 

4. 扩展阅读

如果还是对RSA感到困惑,或者觉得我讲的不是很透彻的话,这里我附上几个参考资料:

RSA算法原理(一):http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html
银行密码系统安全吗?质数(素数)到底有啥用?李永乐老师11分钟讲RSA加密算法(2018最新):https://www.bilibili.com/video/BV1Ts411H7u9/?spm_id_from=333.999.0.0&vd_source=b72e73622847cc3b5219f60be44bf555
公钥密码之RSA:https://www.cnblogs.com/clwsec/p/15680029.html
python的rsa库的使用:https://blog.csdn.net/qq_41621362/article/details/102105642

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值