从XCTF best

    科技2022-09-06  116

    0x00 RSA原理

    明文为m,密文为c 模n = p*q 欧拉函数值φ(n),φ(n)=(p-1)(q-1) 公钥参数e和私钥参数d,可由欧拉函数值计算出,e≡d^-1 (mod φ(n)); 加密:m^e ≡ c (mod n) 解密:c^d ≡ m (mod n)

    0x01 共模攻击的由来

    所谓共模,就是明文m相同,模n相同,用两个公钥e1,e2加密得到两个私钥d1,d2和两个密文c1,c2 共模攻击,即当n不变的情况下,知道n,e1,e2,c1,c2 。可以在不知道d1,d2的情况下,解出m。 这里有个条件,即

    gcd(e1,e2)=1

    0x02 共模攻击原理

    有整数s1,s2(一正一负)

    e1*s1+e2*s2 = 1

    根据扩展欧几里德算法,我们可以得到该式子的一组解(s1,s2),假设s1为正数,s2为负数。

    0x02_1 欧几里得算法

    要了解扩展欧几里得算法,最好先知道欧几里得算法 欧几里得算法:

    d = gcd(a,b) d = gcd(b,a mod b) //这里假设a>b gcd(a,b) = gcd(b,a mod b) 上面就是一次辗转相除 一直辗转相除下去,可得: gcd(a,b) = gcd(b,a mod b) = ... = gcd(m,0) 其中m为最大公约数

    用例:

    gcd(21,15) = gcd(15,6) = gcd(6,3) = gcd(3,0) 即可得21与15的最大公约数为3

    0x02_2 扩展欧几里得算法

    对于不完全为 0 的非负整数 a,b 有gcd(a,b) 必然存在整数对 x,y ,使得 gcd(a,b)=a*x+b*y。

    用代码表示:

    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)

    因为

    c1 = m^e1%n c2 = m^e2%n 所以

    (c1s1*c2s2)%n = ((me1%n)s1*(me2%n)s2)%n 化简得 c1^s1 * c2^s2 = m

    一个数的负次幂

    在数论模运算中,要求一个数的负数次幂,与常规方法并不一样。

    比如此处要求c2的s2次幂,就要先计算c2的模反元素c2r,然后求c2r的-s2次幂 所以我们有以下脚本:

    0x03 解题脚本

    from Crypto.PublicKey import RSA from Crypto.Util.number import * from gmpy2 import * 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) f1 = open('publickey1.pem','rb').read() pub1 = RSA.importKey(f1) n = int(pub1.n) e1 = int(pub1.e) f2 = open('publickey2.pem','rb').read() pub2 = RSA.importKey(f2) e2 = int(pub2.e) c1 = open('cipher1.txt','rb').read() c1 = bytes_to_long(c1) print(c1) c2 = open('cipher2.txt','rb').read() c2 = bytes_to_long(c2) print(c2) print(gcd(e1,e2)) s = egcd(e1, e2) s1 = s[1] s2 = s[2] if s1 < 0: s1 = - s1 c1 = invert(c1, n) elif s2 < 0: s2 = - s2 c2 = invert(c2, n) m = pow(c1,s1,n)*pow(c2,s2,n) % n print (long_to_bytes(m))
    Processed: 0.008, SQL: 9