A向B广播一条消息:B,我有要事汇报
B立即生成两个大素数,p,q 算出n=p*q 并取一个素数 e=65537 广播 n,e 即加密密钥
A收到了n,e 攻击者也收到了n,e
A立即将情报通过hex和padding 转换成一串数字 m 算m^e mod n = c 即 c = pow(m,e,n)
此时 A手上有 n,e,m,c 想把c传给B
广播通信出去 B 收到了c 攻击者收到了c
目前 A 有 n,e,m,c B 有 p,q,n,e,c
攻击者 有 n,e,c
B 比攻击者多了 p,q 计算e关于n的欧拉函数的逆元 即 ed = 1 mod (n) (n) 是 n 的欧拉函数 即 (n) = (p-1)(q-1)
可通过扩展的欧几里得算法求出d
import primefac d = primefac.modinv ( e , (p-1) * (q-1) ) % ( (p-1) * (q-1) )B 又多了个d 可算出 m = c^d mod n 即 m = pow(c,d,n) B 最终得到m 是 A 发过来的情报
因为攻击者没有 p,q 就不能算出 d 也就不能解密 c 得到 m
d, n 为此密码的私钥
我画个流程图好理解点 使用openssl 读取pem 文件中的信息 查看公钥文件
openssl rsa -pubin -in pubkey.pem -text -modulus解密结果如下
rsautl -decrypt -inkey private.pem -in flag.enc -out flag2048bit的n 是安全的 通常小于256b 模数分解 pycrypto-2.6.1/ PyCrypto中提供了用于生成大素数、素性检测等的函数
from Crypto.Util.number import long_to_bytes,bytes_to_long,getPrime,isPrime print isPrime(getPrime(1024))输出 1
from Crypto.Util.number import long_to_bytes,bytes_to_long,getPrime,isPrime p=getPrime(128) q=getPrime(128) n=p*q print p print q print n输出
264557343544462264095085670795796368069 254600537743868350285359152454615998047 67356441930509410513140786204783020450831743401635998443649164089866197161243示例yafu分解 例题1、 假如题目只给了公钥,我们要获取明文 我们只有 n,e,c 为了计算d 从而解出c 首先要把n分解
n=41376961156168948196303384218941117367850019509202049026037168194982219784159 e=65537 c=4161293100530874836836422603625206824589693933040432789074054165274087272587得到
p=130451115685568383270871808144053983073 q=317183651045971246384245233153006206783 from Crypto.Util.number import long_to_bytes,bytes_to_long,getPrime,isPrime import primefac def modinv(a,n): return primefac.modinv(a,n) % n n=41376961156168948196303384218941117367850019509202049026037168194982219784159 e=65537 c=4161293100530874836836422603625206824589693933040432789074054165274087272587 p=130451115685568383270871808144053983073 q=317183651045971246384245233153006206783 d=modinv(e,(p-1)*(q-1)) m=pow(c,d,n) print long_to_bytes(m) //m转换成字符串输出
直接分解n成功的原因是两个素数太小,导致直接爆破 p,q都是素数也是奇数, 存在 a=(p+q)/2,b=(p-q)/2 n=a^ 2 - b^2 即通过枚举大于n的完全平方数 就可以分解n 这种方法适用于p,q差距很小的情况 因为(p-q)/ 2 的值就很小
通过某种方法得到两个整数a,b 计算 p = gcd ( a-b,n ) 最大公约数 直到p不为1 或者a,b 出现循环为止
判断p==n ?n是质数:p是n的一个因子
递归计算Pollard§ 和Pollard(n/p) 求出n的所有质因子
使用函数 X2 = X1^2+c 计算a,b 通常取c=1 即 b=a^2+1 然后把b的值赋给a 再求出新的b 直到 a,b 出现循环
这种方法适用于p或q其中一方过小 即p,q差距大
如果A和B进行两次通信 B两次产生的p,q 有一个假设p出现了两次 那么攻击者可以通过最大公约数计算n1,n2共同的因子p 通过除p 分解n1,n2
题目给出n1 n2 c1 c2 e1 e2 求n1 n2的最大公约数 得到p1==p2 再求q1 q2 得到d1 d2 由 c d n 得到 m1 m2
p1=primefac.gcd(n1,n2) p2=p1 q1=n1/p1 q2=n2/p2 e1=65537 e2=65537 d1=modinv(e1,(p1-1)*(q1-1)) d2=modinv(e2,(p2-1)*(q2-1)) m1=pow(c1,d1,n1) m2=pow(c2,d2,n2) print long_to_bytes(m1) print long_to_bytes(m2)