Crypto

共模之谜

题目名称:共模之谜
题目描述:情报部门截获了两条来自同一来源的加密信息,它们使用了相同的RSA模数但不同的公钥指数。这种看似冗余的操作背后可能隐藏着严重的安全隐患。你能利用这一漏洞还原出原始情报吗?

题目给出了如下数据:

1
2
3
4
5
n =  52434676028442864513479128215013580182283012674942942342267825274916668125023466810480258585751372421292748168448504340890831865866538692974717102950393572887019518607310927816328323922713991044821625309344713196448648512424001395920800511116740568322697525090524941927457199617152790810652838307470708198191
e1 = 65535
e2 = 65537
c1 = 31521924348336802941777804619118889419878299906419071463959824967144080278171748396111541024836589397246436103266770875084999045862006933555188252327690337535968633887854737591285586725332567987630507078395008745655466830366884621022676739454737019137093537940861470289530663521973352477282432379221618425173
c2 = 36458358677472463740424671249382188611575270134299259491605236563200229724936493457180763895249374203908007428278380931503316461352600040412306743430776089418505336838252318935614227276154885340185203325582856170342370595170507594127231199036370588508651117489152775119699195183906973863975443599121572830617

提示:当同一明文 m在相同的模数 n下被两个互质的公钥指数 e1,e2加密时,攻击者可通过扩展欧几里得算法找到一组整数 s,t满足 s⋅e1+t⋅e2=1,进而直接计算 m

实际上这就是共模攻击。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import gmpy2
from Crypto.Util.number import long_to_bytes


n = 52434676028442864513479128215013580182283012674942942342267825274916668125023466810480258585751372421292748168448504340890831865866538692974717102950393572887019518607310927816328323922713991044821625309344713196448648512424001395920800511116740568322697525090524941927457199617152790810652838307470708198191
e1 = 65535
e2 = 65537
c1 = 31521924348336802941777804619118889419878299906419071463959824967144080278171748396111541024836589397246436103266770875084999045862006933555188252327690337535968633887854737591285586725332567987630507078395008745655466830366884621022676739454737019137093537940861470289530663521973352477282432379221618425173
c2 = 36458358677472463740424671249382188611575270134299259491605236563200229724936493457180763895249374203908007428278380931503316461352600040412306743430776089418505336838252318935614227276154885340185203325582856170342370595170507594127231199036370588508651117489152775119699195183906973863975443599121572830617



g, s1, s2 = gmpy2.gcdext(e1, e2)
assert g == 1, "e1 and e2 不互质"

if s1 < 0:
    c1 = gmpy2.invert(c1, n)
    s1 = -s1
if s2 < 0:
    c2 = gmpy2.invert(c2, n)
    s2 = -s2

m_part1 = pow(c1, s1, n)
m_part2 = pow(c2, s2, n)
m = (m_part1 * m_part2) % n
print("结果",long_to_bytes(m).decode())

flag{528d82e8ad37e7aeca4c60d475dc056b}

三次方的陷阱

题目名称:三次方的陷阱
题目描述:在一次网络取证中,你发现攻击者留下了一条RSA加密的密文。据情报显示,加密者为了提升效率,使用了一个极小的公钥指数。然而,这种优化反而引入了致命漏洞。你能利用这一点还原出原始信息吗?

题目给出了如下数据:

1
2
3
n:121383870071311775359911942411789216597716521631089762926488206150018405982242606657064334331128377877618291611912838143522718043048975642123842910378536861304156503028830728263614462484834569011277782682653550833803057515742235247213351034112654400245411355170987970439052312230073603288646796930218863851531
e:3
c:2217344750798710450802454256530905633991914822718944829361939093715780428997238569636656782796294509135735606047120598053449689542122515721333911857696093436383317783079856772999993481426122938079821372867463989809098932628954263602024896175828059384261351520201111250580837

当 e=3且明文 m较短时(即 m^3<n),密文 c=m ^e mod n可能直接等于 m^3(未模 n溢出)。此时可直接对 c开三次方根得到 m。
计算 c的立方根(如使用 Python 的 gmpy2.iroot),将得到的整数 m转换为字节串,即还原明文 flag

实际上就是低加密指数攻击:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def integer_nth_root(a,n):
    low = 0
    high = 1 << ((a.bit_length() + n -1) // n+1)
    while low + 1 < high:
        mid = (low+high) // 2
        mid_n = pow(mid,n)
        if mid_n == a:
            return mid, True
        if mid_n < a:
            low = mid
        else:
            high = mid
    return low, pow(low, n) == a


def int_to_bytes(i):
    if i == 0:
        return b"\x00"
    blen = (i.bit_length() +7) // 8
    return i.to_bytes(blen, byteorder='big')


n = 12138387***
e = 3
c = 221734475079871***
m_root, exact = integer_nth_root(c, e)

if exact:
    m_bytes = int_to_bytes(m_root)
    try:
        print("明文",m_bytes.decode())
    except Exception:
        print("只能以十六进制展示",m_bytes.hex)

else:
    print("不符合低指数开放")

flag{9955792527865472523f8b95be1a2718}