2022.4.25 RSA学习记录
RSA学习记录
〇.数论基础
1.同余
若a,b为两个整数,且它们的差a- b能被某个自然数m所整除,则称a就模m来说同余于b ,或者说a和b关于模m同余,记为: a≡b(modm)。它意味着: a-b=m*k (k为某一个整数)。
性质
2.模逆元
这个比较难理解,模运算中是没有小数这一说 的,哪来的倒数呢?其实我们理解的话可以抽象地类比实数的逆元,逆元的概念在线性代数中提到,就是两者相乘为1,a和b相乘取余运算以后还为1,那我们当然就很自然的管他们叫模逆元,或者模倒数了,即相乘的取模运算结果为一。
几种求模逆元算法
1.Python第三方包Crypto的inverse()函数
from Crypto.Util.number import inverse
print(inverse(3,7)) # 3是要求逆元的数,7是模数n
2.Python第三方包gmpy2的invert()函数
from gmpy import invert
print(inverse(3,7)) # 3是要求逆元的数,7是模数n
3.欧拉函数
一. RSA原理解析
名称由来:RSA是1977年由罗纳德李维斯特( Ron Rivest)、阿迪.萨莫尔( AdiShamir )和伦纳德.阿德曼( LeonardAdleman) -起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
首先借用一下bilibili李老师的视频来说明RSA的原理,方便回头复习....
RSA属于非对称加密,我们先了解一下非对称加密的运作流程。
1.1 RSA的非对称加密信息传递
A向B发送信息的过程如下,对应老师最左边的板书.
- 首先B向A传递公钥
- 然后A进行公钥加密算法将明文m变成密文c
- 接着A将生成的密文传递给B
- 最后B进行私钥进行私钥解密算法还原出明文m.
1.2 RSA的具体加解密过程
1.3 RSA的参数含义
后面哪个参数看不懂的话方便回头查阅...
- p&q:两个大质数
- N|n:大整数,也叫模数
- e&d:对应公钥与私钥,互为无反数的两个指数
- (N,e) :公钥对,有N
- (N,d):私钥对,也有N
- c和m:密文和明文
- pow(x,y,z):相当于pow(x,y) % z ,先算x的y次方,如果pow() 有第三个参数z,就对z取模。
- 密钥长度:n的二进制位数。如密钥长度为512表示n用二进制表示有512bit
1.4 RSA安全性分析
对于RSA加密算法,公钥(N,e)
是任意公开的,如果要获取明文m
的话,我们可以通过 pow(c,d)%N=1
(即 pow(c,d,N)=1
)这个条件来推导出m,但是 他需要 私钥d
,私钥是我们未知的。
那么获取私钥d
则是破译密码的关键所在。
如果读者读懂了前面的生成私钥d
加密思路,那么不难推导出,可以用欧拉函数φ(n)=(p-1) * (q-1),再通过d * e ≡ 1 mod φ(N)这两个式子来得到私钥d
。
那么我们最后要解决的问题就是如何让大数N分解成为两个质数p&q
。
如果N=21的话,分解很容易,三七二十一嘛,但...如果N是个1024位的数字,你再让他分解成两个质数呢?现代估计只有量子计算机可能可以做到,所以RSA是安全的。
难啊!!太难了!!大数太难分解了!!RSA牛逼哇!!
1.5 RSA的数学证明
本人太懒了,先抄xiaoJi师傅的作业。。。
主要用到的两个定理是欧拉定理和费马小定理。
费马小定理:a是整数,p是质数,则a^p==a(mod p),如果a不是p的倍数,还有a^(p-1) ≡ 1(mod p)
ps:过几天再补充这方面内容,请及时监督俺....
二、RSA加密篇
# !/usr/bin/python2.7
# encoding: utf-8
from Crypto.Util.number import *
import gmpy2
# 明文m
msg = 'this_is_my_secret'
# 转成16进制整数
hex_msg=int(msg.encode("hex"),16)
print(hex_msg)
# 素数p
p=getPrime(100)
# 素数q
q=getPrime(100)
# n是两个素数的乘积
n=p*q
# 公钥是n,e,e是一个素数。私钥是n,d
e=0x10001
#
phi=(p-1)*(q-1)
# d是e模 varphi(n) 的逆元,d是由e,p,q可以求解出的
d=gmpy2.invert(e,phi)
print("d=",hex(d))
# 密文c
c=pow(hex_msg,e,n)
print("e=",hex(e))
print("n=",hex(n))
print("c=",hex(c))
三、RSA解密篇
首先使用sage把大数n分解成两个质数相乘
脚本如下
#!/usr/bin/python2.7
# encoding:utf-8
import binascii
import gmpy2
# 两个素数的乘积n
n= 0xe3ff649b5179d9301d75c60ba45fa3d6634706404d5c326e63L
#这边我用sage把n分解出两个质因子,yafu也是可以的
p=1159263421820535873212939666333
q=1234546251533207411074736527871
# 公钥e
e=0x10001
# 密文c
c=0x975f285f0e10f661c5eb3344137c333b5b748fdd94814c933fL
phi=(p-1)*(q-1)
# 逆元d
d=gmpy2.invert(e,phi)
# 明文m
m=pow(c,d,n)
print(hex(m))
print(binascii.unhexlify(hex(m)[2:].strip("L")))
运行结果,确实得到了明文“this_is_my_secret”