最近觉得自己的密码学真的是采得一塌糊涂,要重新做人
从最基础的RSA开始吧,也参考了好多大佬的博客
http://www.freebuf.com/sectool/163781.html
https://www.anquanke.com/post/id/84632
https://blog.csdn.net/kevin66654/article/details/53898465
https://blog.csdn.net/veritas501/article/details/55257957
RSA加密基本原理
选择两个大素数p和q,计算出模数N = p * q
计算φ = (p−1) * (q−1) 即N的欧拉函数,然后选择一个e (1
B≡A^e (mod N) 或 B = pow(A,e,N),得到的B即为密文
对密文B进行解密,A≡B^d( mod N) 或 A = pow(B,d,N)
,得到的A即为明文
大家一般性用python的pow函数的时候只用两个参数,这里三个参数是不一样的用法,算是昨晚次方运算后对n取模
p 和 q :大整数N的两个因子(factor)
N:大整数N,我们称之为模数(modulus)
e 和 d:互为模反数的两个指数(exponent)
c 和 m:分别是密文和明文,这里一般指的是一个十进制的数
一般有如下称呼:
(N,e):公钥
(N,d):私钥
模数分解
关键就是把大数N分解为两个素数p,q,只要能分解出来,一切都好说
假设我们分解除了p,q,则φ已知
我们已知e * d ≡ 1 (mod φ),那么在已知e与φ的情况下,就可以直接求出私钥d
怎么求解呢,为了再次加深理解,我又去翻了翻信安数学基础----一次同余式求解
若要这个方程有解,首先要满足gcd(e,φ)=1 #gcd:求两个数的最大公约数,
def gcd(a, b): #求最大公约数
if a < b:
a, b = b, a
while b != 0:
temp = a % b
a = b
b = temp
return a
当然在CTF中这一步大部分情况可以省略,如果不符合这个也没法攻击
接下来采取迭代来使用广义Euclid求出是否有符合的整数x,y
def egcd(a, b): #egcd:求满足ax+by=1,当gcd(a,b)=1时,满足式子的x和y
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
若以上条件不成立,则无法求出私钥d
知道密钥之后,直接解密就好了:m=pow(c,d,N) #c表示密文,m表示明文
分解大素数N以及别的一些攻击方式
有时候题目不会给我们p,q,而是直接给我们大素数N,需要我们自己来分解
1. 如果n在768bit或者更高,可以尝试使用一些在线的n分解网站,这些网站会存储一些已经分解成功的n,
比如:http://factordb.com
这个网站成功率还是蛮高的
2. 有时候会遇到一种题目,就是采用的公钥e都相同,但是两个加密的大素数N都不同,经常让人一头雾水,这种情况下,这些大素数N会有相同的素数因子,那我们直接求公约数就好了,求出公约数后,就可以把另一个素数因子也求出来
def gcd(a, b):
if a < b:
a, b = b, a
while b != 0:
temp = a % b
a = b
b = temp
return a
3. 还遇见过一种情况,公钥e特别小
比如e=3,你对明文m加密,m^3显然比大素数N小许多,那直接对密文c开三次方就完事了
或者说三次方之后就比N大一点点,那我们假设他们相差的值为k,我们不断爆破k开三次方就行
i=0
while 1:
if(gmpy.root(c+i*N, 3)[1]==1):
print gmpy.root(c+i*N, 3)
break
i=i+1
4. 共模攻击
如果在RSA的使用中使用了相同的模N对相同的明文m进行了加密,那么就可以在不分解n的情况下还原出明文m的值,说白就是取得e不一样
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
s = egcd(e1, e2)
s1 = s[1]
s2 = s[2]
print s
n=n1
if s1<0:
s1 = - s1
c1 = modinv(c1, n)
elif s2<0:
s2 = - s2
c2 = modinv(c2, n)
m=(pow(c1,s1,n)*pow(c2,s2,n)) % n
5. 只要p和q存在相差过大或者过近时,都可以通过yafu很快地分解成功
openssl
有些题目提供enc和pem文件,这个时候就是Linux下的工具openssl登场的时候了
openssl 语句:
从公钥中读取e和n:openssl rsa -pubin -text -modulus -in warmup -in 【public.pem】
Rsatool.py生成指定的私钥:python rsatool.py -o 【private.pem】 -e 【65537】 -p 【123】-q 【123】
用私钥解密:openssl rsautl -decrypt -in 【flag.enc】 -inkey 【private.pem】
这我也不知道该怎么说,拿个例题吧
Medium RSA------Jarvis OJ
下载下来是个压缩包,打开一看两个文件
然后跑出公钥
接着直接用http://factordb.com分解大素数N得到p,q
然后生成私钥d,需要rsatool,给个链接:https://blog.csdn.net/veritas501/article/details/55257957
最后再用openssl解密