Crypto_[羊城杯 2020]RRRRRRRSA

[羊城杯 2020]RRRRRRRSA

题目描述

import hashlib
import sympy
from Crypto.Util.number import *

flag = 'GWHT{************}'

flag1 = flag[:19].encode()
flag2 = flag[19:].encode()
assert(len(flag) == 38)

P1 = getPrime(1038)
P2 = sympy.nextprime(P1)
assert(P2 - P1 < 1000)

Q1 = getPrime(512)
Q2 = sympy.nextprime(Q1)

N1 = P1 * P1 * Q1
N2 = P2 * P2 * Q2

E1 = getPrime(1024)
E2 = sympy.nextprime(E1)

m1 = bytes_to_long(flag1)
m2 = bytes_to_long(flag2)

c1 = pow(m1, E1, N1)
c2 = pow(m2, E2, N2)


output = open('secret', 'w')
output.write('N1=' + str(N1) + '\n')
output.write('c1=' + str(c1) + '\n')
output.write('E1=' + str(E1) + '\n')
output.write('N2=' + str(N2) + '\n')
output.write('c2=' + str(c2) + '\n')
output.write('E2=' + str(E2) + '\n')
output.close()

分析程序

感觉是正常的RSA的加密过程

N 1 = p 1 ∗ p 1 ∗ q 1 N1=p1*p1*q1 N1=p1p1q1

N 2 = p 2 ∗ p 2 ∗ q 2 N2=p2*p2*q2 N2=p2p2q2

注意条件:

p 1 p1 p1 p 2 p2 p2是相邻的素数,且两者差值小于1000

q 1 q1 q1 q 2 q2 q2也是相邻的素数

换而言之, p 1 / p 2 ≈ 1 p1/p2\approx 1 p1/p21

看到两个数的比例接近于1,这里有一个相关比例接近的攻击方式维纳攻击


传统的维纳攻击

e ∗ d ≡ 1 ( m o d   f a i ( n ) ) e*d\equiv 1 (mod~fai(n)) ed1(mod fai(n))

e ∗ d − 1 = k ∗ f a i ( n ) e*d-1=k*fai(n) ed1=kfai(n)

等式两边同时除以 d ∗ f a i ( n ) d*fai(n) dfai(n)

得到

e f a i ( n ) − k d = 1 d ∗ f a i ( n ) \frac{e}{fai(n)}-\frac{k}{d}=\frac{1}{d*fai(n)} fai(n)edk=dfai(n)1

f a i ( n ) ≈ N fai(n)\approx N fai(n)N

e N − k d = 1 d ∗ N \frac{e}{N}-\frac{k}{d}=\frac{1}{d*N} Nedk=dN1

显然 1 d ∗ N ≈ 0 \frac{1}{d*N}\approx 0 dN10

又公钥 ( e , N ) (e,N) (e,N)已知

根据维纳攻击的相关定理:

Continued Fractions’Convergents

Let y = r / s y = r/s y=r/s​ be any rational such that ∣ r / s − x ∣ < 1 / ( 2 ∗ s 2 ) | r/s − x| < 1 /(2*s^2) r/sx<1/(2s2)​ . Then y y y is equal to one of the convergents of x , i . e x, i.e x,i.e. y = y i y = y_i y=yi for some i ∈ { 1 , . . . , n } i ∈ \{1,...,n\} i{1,...,n}​.

也就是说, e N \frac{e}{N} Ne​的连分数展开式的收敛到某一位会等于 k d \frac{k}{d} dk

当且仅当 ∣ e N − k d ∣ < 1 2 ∗ d 2 |\frac{e}{N}-\frac{k}{d}|<\frac{1}{2*d^2} Nedk<2d21


从上面的“当且仅当”的条件我们对比出

这道题显然 e > N e>N e>N​所以 e N − k d \frac{e}{N}-\frac{k}{d} Nedk​不能很肯定地说一定满足条件

本题应用的维纳攻击方式

但是这里我们可以用另外一个相近比例

N 1 N 2 ≈ Q 1 Q 2 \frac{N1}{N2}\approx \frac{Q1}{Q2} N2N1Q2Q1​​

那为什么我们不用 N 1 N 2 ≈ P 1 P 2 \frac{N1}{N2}\approx \frac{P1}{P2} N2N1P2P1​呢

我们可以来比较一下

N 1 N 2 = P 1 2 P 2 2 ∗ Q 1 Q 2 \frac{N1}{N2}=\frac{P1^2}{P2^2}*\frac{Q1}{Q2} N2N1=P22P12Q2Q1

  • 如果我们使用 N 1 N 2 ≈ Q 1 Q 2 \frac{N1}{N2}\approx \frac{Q1}{Q2} N2N1Q2Q1

那么可以写做 N 1 N 2 = P 1 2 P 2 2 ∗ Q 1 Q 2 \frac{N1}{N2}=\frac{P1^2}{P2^2}*\frac{Q1}{Q2} N2N1=P22P12Q2Q1

这就意味着 N 1 N 2 \frac{N1}{N2} N2N1 Q 1 Q 2 \frac{Q1}{Q2} Q2Q1的比值为 ( P 1 P 2 ) 2 (\frac{P1}{P2})^2 (P2P1)2

P 1 P1 P1 P 2 P2 P2的差值小于1000

  • 如果使用 N 1 N 2 ≈ P 1 P 2 \frac{N1}{N2}\approx \frac{P1}{P2} N2N1P2P1

那么写作 N 1 N 2 = P 1 P 2 ∗ Q 1 Q 2 ∗ P 1 P 2 \frac{N1}{N2}=\frac{P1}{P2}*\frac{Q1}{Q2}*\frac{P1}{P2} N2N1=P2P1Q2Q1P2P1

那么 N 1 N 2 \frac{N1}{N2} N2N1 P 1 P 2 \frac{P1}{P2} P2P1的比值为 P 1 P 2 ∗ Q 1 Q 2 \frac{P1}{P2}*\frac{Q1}{Q2} P2P1Q2Q1

  • 显然当两者的比值越小时,两者的差值越小

由已知条件( P 2 − P 1 < 1000 P2-P1<1000 P2P1<1000)我们可以知道 ( P 1 P 2 ) 2 (\frac{P1}{P2})^2 (P2P1)2很可能小于(不能确定) P 1 P 2 ∗ Q 1 Q 2 \frac{P1}{P2}*\frac{Q1}{Q2} P2P1Q2Q1

所以我们优先选择 N 1 N 2 ≈ Q 1 Q 2 \frac{N1}{N2}\approx \frac{Q1}{Q2} N2N1Q2Q1

  • 另外还有一点

选择 N 1 N 2 ≈ P 1 P 2 \frac{N1}{N2}\approx \frac{P1}{P2} N2N1P2P1可以进行维纳攻击的前提条件是:

∣ N 1 N 2 − P 1 P 2 ∣ < 1 2 ∗ P 2 2 |\frac{N1}{N2}-\frac{P1}{P2}|<\frac{1}{2*P_2^2} N2N1P2P1<2P221

而选择 N 1 N 2 ≈ Q 1 Q 2 \frac{N1}{N2}\approx \frac{Q1}{Q2} N2N1Q2Q1​可以进行维纳攻击的前提条件是:

∣ N 1 N 2 − Q 1 Q 2 ∣ < 1 2 ∗ Q 2 2 |\frac{N1}{N2}-\frac{Q1}{Q2}|<\frac{1}{2*Q_2^2} N2N1Q2Q1<2Q221

通过看加密程序我们可以知道

Q1 = getPrime(512)
Q2 = sympy.nextprime(Q1)
P1 = getPrime(1038)
P2 = sympy.nextprime(P1)

显然选择 N 1 N 2 ≈ P 1 P 2 \frac{N1}{N2}\approx \frac{P1}{P2} N2N1P2P1的前提条件更苛刻( 1 2 ∗ P 2 2 < 1 2 ∗ Q 2 2 \frac{1}{2*P_2^2}<\frac{1}{2*Q_2^2} 2P221<2Q221

已知 N 1 , N 2 N1,N2 N1,N2

把它换做连分数形式

这里应用扩展欧几里得算法和连分数之间的联系

x = a 1 ∗ y + r 1 x=a_1*y+r_1 x=a1y+r1​​​​​

x = a 2 ∗ r 1 + r 2 x=a_2*r_1+r_2 x=a2r1+r2​​

r 1 = a 3 ∗ r 2 + r 3 r_1=a_3*r_2+r_3 r1=a3r2+r3

连分数:

x / y = a 1 + 1 a 2 + 1 a 3 + . . . x/y=a_1+\frac{1}{a_2+\frac{1}{a_3+...}} x/y=a1+a2+a3+...11​​

相信大家已经看出两者的联系了

这里开始想办法使用python实现将分数转换为连分数,并且分别输出分子,分母

先使用扩展欧几里得算法获得每次辗转相除法得到的 a 1 , a 2 , a 3 . . . a_1,a_2,a_3... a1,a2,a3...

def exgcd(x,y):
	result = []
	if y > x:
		x,y = y,x
	while y:
		result.append(x//y)
		x,y = y,x % y
     return result

然后使用 a 1 , a 2 , a 3 . . . a_1,a_2,a_3... a1,a2,a3...​​​​形成 x / y x/y x/y​​​​的连分数

for n in range(1,len(result)):
	temp = result[:n]
	num = 0 # 分子初始化
	deno = 1 # 分母初始化
	for i in temp[::-1]:
		num,deno = deno,deno*i + num

这里求解分子,分母的过程显得有点点难以理解,可以自己随便找两个例子推一推。

再将这里第二个for循环中赋值得到的分子和分母去进行下一步比较:

类比传统的维纳攻击中的判断条件 ( e ∗ d − 1 ) % k = = 0 (e*d-1)\%k==0 (ed1)%k==0

N 1   %   d e n o = 0 N1 ~\%~deno=0 N1 % deno=0​且 d e n o ≠ 1 deno\neq 1 deno=1​即可认定这个 d e n o deno deno​为 Q 1 Q1 Q1

得到了 Q 1 Q1 Q1​后面的就是正常的RSA求解了

代码实现

from Crypto.Util.number import *
import gmpy2,sympy

N1=60143104944034567859993561862949071559877219267755259679749062284763163484947626697494729046430386559610613113754453726683312513915610558734802079868190554644983911078936369464590301246394586190666760362763580192139772729890492729488892169933099057105842090125200369295070365451134781912223048179092058016446222199742919885472867511334714233086339832790286482634562102936600597781342756061479024744312357407750731307860842457299116947352106025529309727703385914891200109853084742321655388368371397596144557614128458065859276522963419738435137978069417053712567764148183279165963454266011754149684758060746773409666706463583389316772088889398359242197165140562147489286818190852679930372669254697353483887004105934649944725189954685412228899457155711301864163839538810653626724347
c1=55094296873556883585060020895253176070835143350249581136609315815308788255684072804968957510292559743192424646169207794748893753882418256401223641287546922358162629295622258913168323493447075410872354874300793298956869374606043622559405978242734950156459436487837698668489891733875650048466360950142617732135781244969524095348835624828008115829566644654403962285001724209210887446203934276651265377137788183939798543755386888532680013170540716736656670269251318800501517579803401154996881233025210176293554542024052540093890387437964747460765498713092018160196637928204190194154199389276666685436565665236397481709703644555328705818892269499380797044554054118656321389474821224725533693520856047736578402581854165941599254178019515615183102894716647680969742744705218868455450832
E1=125932919717342481428108392434488550259190856475011752106073050593074410065655587870702051419898088541590032209854048032649625269856337901048406066968337289491951404384300466543616578679539808215698754491076340386697518948419895268049696498272031094236309803803729823608854215226233796069683774155739820423103
N2=60143104944034567859993561862949071559877219267755259679749062284763163484947626697494729046430386559610613113754453726683312513915610558734802079868195633647431732875392121458684331843306730889424418620069322578265236351407591029338519809538995249896905137642342435659572917714183543305243715664380787797562011006398730320980994747939791561885622949912698246701769321430325902912003041678774440704056597862093530981040696872522868921139041247362592257285423948870944137019745161211585845927019259709501237550818918272189606436413992759328318871765171844153527424347985462767028135376552302463861324408178183842139330244906606776359050482977256728910278687996106152971028878653123533559760167711270265171441623056873903669918694259043580017081671349232051870716493557434517579121
c2=39328446140156257571484184713861319722905864197556720730852773059147902283123252767651430278357950872626778348596897711320942449693270603776870301102881405303651558719085454281142395652056217241751656631812580544180434349840236919765433122389116860827593711593732385562328255759509355298662361508611531972386995239908513273236239858854586845849686865360780290350287139092143587037396801704351692736985955152935601987758859759421886670907735120137698039900161327397951758852875291442188850946273771733011504922325622240838288097946309825051094566685479503461938502373520983684296658971700922069426788236476575236189040102848418547634290214175167767431475003216056701094275899211419979340802711684989710130215926526387138538819531199810841475218142606691152928236362534181622201347
E2=125932919717342481428108392434488550259190856475011752106073050593074410065655587870702051419898088541590032209854048032649625269856337901048406066968337289491951404384300466543616578679539808215698754491076340386697518948419895268049696498272031094236309803803729823608854215226233796069683774155739820425393

def exgcd(x,y):
    mult = []
    if y > x:
        x,y = y,x
    while y:
        mult.append(x//y)
        x,y = y,x % y
    return mult

mult = exgcd(N2,N1) # N1<N2

for n in range(len(mult)):
    temp = mult[:n]
    num = 0 # 分子
    deno = 1 # 分母
    for x in temp[::-1]:
        num,deno = deno, deno * x + num
    if N2 % deno == 0 and deno != 1:
        Q2 = deno
        print(Q2)
        break
Q1 = sympy.prevprime(Q2)
P1 = gmpy2.iroot(N1 // Q1,2)[0]
P2 = gmpy2.iroot(N2 // Q2,2)[0]
fai_n1 = (P1-1)*P1*(Q1-1)
fai_n2 = (P2-1)*P2*(Q2-1)
d1 = gmpy2.invert(E1,fai_n1)
d2 = gmpy2.invert(E2,fai_n2)
m1 = pow(c1,d1,N1)
m2 = pow(c2,d2,N2)
print(bytes.decode(long_to_bytes(m1)),end="")
print(bytes.decode(long_to_bytes(m2))) 

参考文章

Wiener’s Attack Ride(维纳攻击法驾驭) - 知乎 (zhihu.com)

(60条消息) 密码学硬核笔记——扩展维纳攻击_Gm1y’s Blog-CSDN博客_扩展维纳攻击

(60条消息) RSA攻击之wiener攻击_oumeixi_wjp的专栏-CSDN博客_wiener攻击

LNCS 3386 - Converse Results to the Wiener Attack on RSA (springer.com)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

M3ng@L

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值