RSA攻击

2019-04-13 15:34发布

最近觉得自己的密码学真的是采得一塌糊涂,要重新做人 从最基础的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 (1B≡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解密        

热门文章