【无标题】

文章详细介绍了RSA加密算法的几种攻击方式,包括共模攻击、因数碰撞法、费马分解法、Pollardp-1分解法和低加密指数攻击,展示了如何利用这些方法从截获的加密数据中恢复明文和参数,强调了RSA加密安全性的重要性。
摘要由CSDN通过智能技术生成

RSA大礼包

题目描述

RSA加密算法中包含了五个参数,包括两个素数p和q、模数N=pq、加密指数e和解密指数d。如果RSA加密的参数选取不当,同样存在被破解的可能。已知某人使用RSA加解密软件发送了一个明文,其中所有加密数据已被截获,在这些加密的数据中存在着各种参数选择不当的问题,导致加密的安全性受到影响。我们需要从加密数据恢复该明文及RSA体制的参数,并给出明文和参数。

解题过程

首先需要解析密文的结构,帧数据的数据格式如下,其中数据都是 16 进制表示,结构如下 1024bit模数N | 1024bit加密指数e | 1024bit密文me mod N。解析了帧的结构后可以对密文进行分析。
在本题中主要用到的攻击方式有下面几种

1,共模攻击

共模攻击即用两个及以上的公钥(n,e)来加密同一条信息m。已知有密文:c1 = pow(m, e1, n),c2 = pow(m, e2, n),当e1,e2互质,则有gcd(e1,e2)=1,根据扩展欧几里德算法,对于不完全为 0 的整数 a,b,gcd(a,b)表示 a,b 的最大公约数。那么一定存在整数x,y使得gcd(a,b)=ax+by。所以得到:e1s1+e2s2=1。因为e1和e2为正整数,所以s1、s2皆为整数,但是一正一负,此时假设s1为正数,s2为负数。

def common_modulus_attack(ns,es,cs):
    # 寻找公共模数
    index1 = 0
    index2 = 0
    for i in range(21):
        for j in range(i+1, 21):
            if ns[i] == ns[j]:
                #print('Same modulus found! ({}, {})'.format(i, j))
                index1, index2 = i, j
    e1 = int(es[index1], 16)
    e2 = int(es[index2], 16)
    n = int(ns[index1], 16)
    c1 = int(cs[index1], 16)
    c2 = int(cs[index2], 16)

    g, s1, s2 = extended_gcd(e1, e2)
    # 求模反元素
    if isinstance(s1, int) and s1 < 0:
        s1 = -s1
        c1 = gmpy2.invert(c1, n)
    elif isinstance(s2, int) and s2 < 0:
        s2 = -s2
        c2 = gmpy2.invert(c2, n)
    m = pow(c1, s1, n) * pow(c2, s2, n) % n
    #print('Recovered message: {}'.format(hex(m)))
    result = binascii.a2b_hex(hex(m)[2:])
    return result

2,因数碰撞法

因数碰撞法是指,如果p或者q在多个RSA加密中出现多次,那么生成不同的n可能会有相同的因子,假设p相同,q不同,那么有 n1=pq1,n2=pq2。易得 gcd(n1,n2)=p。这样就可以将其各自的私钥解出来了。

def factor_collision_attack(ns,es,cs):
    p, index1, index2 = None, None, None
    for i in range(21):
        for j in range(i+1, 21):
            if int(ns[i], 16) == int(ns[j], 16):
                continue
            gcd = gmpy2.gcd(int(ns[i], 16), int(ns[j], 16))
            if gcd != 1:
                p, index1, index2 = gcd, i, j
                break
        if p:
            break

    q1 = int(ns[index1], 16) // p
    q2 = int(ns[index2], 16) // p
    phi1 = (p-1)*(q1-1)
    phi2 = (p-1)*(q2-1)
    d1 = gmpy2.invert(int(es[index1], 16), phi1)
    d2 = gmpy2.invert(int(es[index2], 16), phi2)
    plaintext1 = gmpy2.powmod(int(cs[index1], 16), d1, int(ns[index1], 16))
    plaintext2 = gmpy2.powmod(int(cs[index2], 16), d2, int(ns[index2], 16))
    return [binascii.a2b_hex(hex(plaintext1)[2:]), binascii.a2b_hex(hex(plaintext2)[2:])]

3,使用费马分解法分解n

费马分解法是一种基于数论的因数分解算法,可以用于破解RSA加密算法。其基本思路是通过找到一个接近平方根的数,来使得模数n和这个数的平方的差刚好是一个完全平方数。接着,通过对这个完全平方数开方,得到两个因子,从而分解出n的因子。

#使用费马分解法分解n
def fermat_factorization(n): 
    B = math.factorial(2**14)
    u = 0
    v = 0
    i = 0
    u0 = gmpy2.iroot(n, 2)[0] + 1
    while i <= (B - 1):
        u = (u0 + i)**2 - n
        if gmpy2.is_square(u):
            v = gmpy2.isqrt(u)
            break
        i = i + 1  
    p = u0 + i + v
    return p
#输出费马分解法攻击的结果
def get_content_of_frame10(ns):
    # 分解Frame 10
    n = int(ns[10], 16)
    p = fermat_factorization(n)
    # 已知p,直接计算q和phi(n)
    c = int(cs[10], 16)
    e = int(es[10], 16)
    q = n // p
    phi_n = (p - 1) * (q - 1)
    # 计算私钥d并解密
    d = gmpy2.invert(e, phi_n)
    m = gmpy2.powmod(c, d, n)
    final_plain = binascii.a2b_hex(hex(m)[2:])
    return final_plain

4,Pollard p-1分解法攻击

Pollard p-1分解法的核心思想是利用数学中的一些性质,通过选择合适的参数来使得因子较小的数的概率增加,从而更容易进行分解。
算法的基本原理是,假设我们要分解的RSA加密算法中使用的质数p是在一个相对较小的范围内,我们可以选择一个合适的整数a,使得a的幂次数连续乘起来与p取模的结果包含了一些小的质因数。具体来说,假设a的幂次数连续乘起来为b = a^(k1) * a^(k2) * … * a^(kr),其中ki表示每个幂次数,r表示幂次数的个数,那么我们可以通过计算gcd(b-1,p) 来得到p的一个因子。
Pollard p-1分解法并不能保证一定能够分解出 RSA 加密算法中使用的质数,因为它依赖于a的选择和幂次数的取值,如果选择的参数不合适或者幂次数取值不合理,那么可能无法得到有效的结果。

#Pollard p-1分解法攻击
def pollard_p_minus_1_factorization(n):
    b = 2**20
    a = 2
    for i in range(2, b+1):
        a = pow(a, i, n)
        d = gmpy2.gcd(a - 1, n)
        if 1 < d < n:
            return d
    return None
def pollard_resolve(ns,es,cs): 
    index_list = [2, 6, 19]
    plaintexts = []
    for i in index_list:
        n = int(ns[i], 16)
        c = int(cs[i], 16)
        e = int(es[i], 16)
        p = pollard_p_minus_1_factorization(n)
        #print("p of " + str(i) + " is : " + str(p))
        q = n // p
        phi = (p - 1) * (q - 1)
        d = gmpy2.invert(e, phi)
        m = gmpy2.powmod(c, d, n)
        plaintexts.append(binascii.a2b_hex(hex(m)[2:]))
    return plaintexts

5,低加密指数攻击

5,低加密指数攻击
RSA低加密指数广播攻击是一种攻击RSA加密算法中使用了相同低加密指数的多个密文的情况。攻击者可以通过这些密文来推断出RSA加密中的私钥,从而解密所有其他密文。
攻击的原理基于RSA加密算法中的加密过程,即c=m^e mod n,其中c是密文,m是明文,e是加密指数,n是两个大质数p和q的乘积。在RSA加密中,选择e作为加密指数是非常重要的,通常情况下会选择e=3或e=65537等较小的质数,以便于快速计算密文。
攻击者利用相同的低加密指数e加密多个明文m1,m2,…,mk,得到对应的密文c1,c2,…,ck假设攻击者已经知道e和n并且可以获得每个密文的ci和n的值。然后,攻击者可以使用中国剩余定理来求解me,因为对于i=1,2,…,k,me ≡ ci (mod n),因此 m^e 可以被表示为m^e≡xi(mod p) 和 m^e ≡yi(mod q),其中xi≡ci(mod p),yi≡ci(mod q)。然后,攻击者可以通过求解离散对数问题来计算m,具体来说,可以使用欧拉定理m^(φ(n))≡1(mod n)来计算d=e^(-1)(mod φ(n)),其中φ(n)=(p-1)(q-1) 是欧拉函数,e(-1)表示e在模φ(n)意义下的逆元。最后,攻击者可以通过计算cd(mod n) 来解密所有的密文,因为cd=(me)d=m(ed)≡m(mod n)。

def chinese_remainder_theorem(items): #中国剩余定理
    N = 1
    for a, n in items:
        N *= n
        result = 0
    for a, n in items:
        m = N//n
        d, r, s = extended_gcd(n, m)
        if d != 1:
            N = N//n
            continue
        result += a*s*m
    return result % N, N
# 低加密指数攻击
def bruce_e_3(ns,cs):
    bruce_range = [7, 11, 15]
    for i in range(3):
        c = int(cs[bruce_range[i]], 16)
        n = int(ns[bruce_range[i]], 16)
        print("This is frame" + str(i))
        for j in range(20):
            plain = gmpy2.iroot(gmpy2.mpz(c+j*n), 3)
            print("This is test" + str(j))
            print(binascii.a2b_hex(hex(plain[0])[2:]))
def low_e_3(ns,cs):
    sessions=[{"c": int(cs[7], 16) ,"n": int(ns[7], 16)},
    {"c":int(cs[11], 16) ,"n":int(ns[11], 16)},
    {"c":int(cs[15], 16) ,"n":int(ns[15], 16)}]
    data = []
    for session in sessions:
        data = data+[(session['c'], session['n'])]
    x, y = chinese_remainder_theorem(data)
    # 直接开三次方根
    plaintext7_11_15 = gmpy2.iroot(gmpy2.mpz(x), 3)
    return binascii.a2b_hex(hex(plaintext7_11_15[0])[2:])
def low_e_5(ns,cs):
    sessions=[{"c": int(cs[3], 16),"n": int(ns[3], 16)},
    {"c":int(cs[8], 16) ,"n":int(ns[8], 16) },
    {"c":int(cs[12], 16),"n":int(ns[12], 16)},
    {"c":int(cs[16], 16),"n":int(ns[16], 16)},
    {"c":int(cs[20], 16),"n":int(ns[20], 16)}]
    data = []
    for session in sessions:
        data = data+[(session['c'], session['n'])]
    x, y = chinese_remainder_theorem(data)
    # 直接开五次方根
    plaintext3_8_12_16_20 = gmpy2.iroot(gmpy2.mpz(x),5)
    return binascii.a2b_hex(hex(plaintext3_8_12_16_20[0])[2:])

6,结果分析

经过上述算法后,我们可以通过调用函数来获得部分密文的攻击结果,代码和结果如下

if __name__ == '__main__':
    ns=[] #1024bit模数N
    es=[] #1024bit加密指数e
    cs=[] #1024bit密文m^e mod N
    for i in range(21):
        with open("D:/学习/大作业/现代密码学/RSA加密体制破译/密码挑战赛赛题三/附件3-2(发布截获数据)/Frame"+str(i), "r") as f:
            temp = f.read()
            ns.append(temp[0:256])
            es.append(temp[256:512])
            cs.append(temp[512:768])

    result_0=common_modulus_attack(ns,es,cs)
    #print(result_0) # Frame0 与 Frame4 的解密结果是: My secre
    result_1=factor_collision_attack(ns,es,cs)
    #print(result_1[0]) # Frame1解密结果是: . Imagin
    #print(result_1[1]) # Frame18解密结果是: m A to B
    result_2=get_content_of_frame10(ns)
    #print(result_2) # Frame10解密结果是: will get
    result_3=pollard_resolve(ns,es,cs)
    #print(result_3[0]) # Frame2 解密结果是: That is
    #print(result_3[1]) # Frame6 解密结果是: "Logic "
    #print(result_3[2]) # Frame19 解密结果是: instein.
    result_4=low_e_5(ns,cs)
    #print(result_4) ## Frame3 Frame8 Frame12 Frame16 Frame20 解密结果是: t is a f

总结

RSA加密算法是一种常用的公钥加密算法,但它并不是绝对安全的,存在多种攻击方法可以破解其加密过程。在本次实验中先使用了五种常见的RSA攻击算法,分别是共模攻击、因数碰撞、低加密指数广播攻击、Pollard p-1分解法攻击和费马分解法攻击。最后使用猜测攻击来尝试还原明文。通过本次实验加深了我队RSA加密算法的理解,明白了RSA加密在使用时应注意的事项。

参考文献

Boneh D. Twenty years of attacks on the RSA cryptosystem[J]. Notices of the AMS, 1999, 46(2): 203-213.

https://github.com/blank-vax/RSA_breaking

https://blog.csdn.net/pigeon_1/article/details/114371456

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值