羊城杯-2020-Simple

[羊城杯 2020]Simple

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from Crypto.Util.number import *
from Crypto.Cipher import DES
import gmpy2
from secret import flag
import random

key = "abcdefgh"

def des_encrypt(m):
des = DES.new(key, DES.MODE_ECB)
res = des.encrypt(m)
return res

def gen_key():
p = getPrime(2048)
q = getPrime(2048)
n = p * q
bit = n.bit_length()
phi_n = (p - 1) * (q - 1)#4096bits
num = random.randint(1, 100)
while True:
u = getPrime(bit / 4 - num)#1024bits左右
if gmpy2.gcd(u, phi_n) != 1:
continue
t = gmpy2.invert(u, phi_n)
e = bytes_to_long(des_encrypt(long_to_bytes(t)))
if gmpy2.gcd(e, phi_n) == 1:
break
return (n, e)

P = getPrime(1024)
Q = getPrime(1024)
N = P * Q
E = 65537
lcm = gmpy2.lcm(P-1, Q-1)
e1 = gmpy2.invert(getPrime(730), lcm)
e2 = gmpy2.invert(getPrime(730), lcm)
m = bytes_to_long(flag)
c = pow(m, E, N)
print "N = " + str(N)
print "e2 = " + str(e2)
print "c = " + str(c)
_n, _e = gen_key()
_c = pow(e1, _e, _n)
print "_n = " + str(_n)
print "_e = " + str(_e)
print "_c = " + str(_c)

# N = 14922959775784066499316528935316325825140011208871830627653191549546959775167708525042423039865322548420928571524120743831693550123563493981797950912895893476200447083386549353336086899064921878582074346791320104106139965010480614879592357793053342577850761108944086318475849882440272688246818022209356852924215237481460229377544297224983887026669222885987323082324044645883070916243439521809702674295469253723616677245762242494478587807402688474176102093482019417118703747411862420536240611089529331148684440513934609412884941091651594861530606086982174862461739604705354416587503836130151492937714365614194583664241
# e2 = 27188825731727584656624712988703151030126350536157477591935558508817722580343689565924329442151239649607993377452763119541243174650065563589438911911135278704499670302489754540301886312489410648471922645773506837251600244109619850141762795901696503387880058658061490595034281884089265487336373011424883404499124002441860870291233875045675212355287622948427109362925199018383535259913549859747158348931847041907910313465531703810313472674435425886505383646969400166213185676876969805238803587967334447878968225219769481841748776108219650785975942208190380614555719233460250841332020054797811415069533137170950762289
# c = 6472367338832635906896423990323542537663849304314171581554107495210830026660211696089062916158894195561723047864604633460433867838687338370676287160274165915800235253640690510046066541445140501917731026596427080558567366267665887665459901724487706983166070740324307268574128474775026837827907818762764766069631267853742422247229582756256253175941899099898884656334598790711379305490419932664114615010382094572854799421891622789614614720442708271653376485660139560819668239118588069312179293488684403404385715780406937817124588773689921642802703005341324008483201528345805611493251791950304129082313093168732415486813
# _n = 440489238264900860776949063845200558734341182253911040104689726634414488997095518284964514078079911856352824174173937251558842251349762631716798307360995414545464514355957499460396352456341058329671470384493547042182238690727766731554287411757022792467324815342497916894285866240516524768645049867582541899123632009100512965460004548382054578461249990158442675234477122521189649316341623637146867589119951831385717513964941787562068891523060843170463600255518728070958509224053460041184869943038887434435024428311063533345514827827485121055022245800823723487812635502090530820946638405345755666124356919178290008475459419571761406117827422883820901663916276191422633940699113760516149002609672230610575442643822241126824287790055264162725209120192661985259423924307785452001927701323647247782658775780117642900694831475681037634691806232211286493187121464506122012889644137364079403183353774265910554863733455161820449073656744610495110838881353269890437984975607744603113572453211439334880155671730821755361054781243639407912133971530394031933785051770725331242932929244719594830548310768937037042243794551163891451545574837838357398072638709907958216067999891842395376953596940377457308329336524488962532620850237570279134567668379
# _e = 861605654852236668414010386016782729745549477722901970933220380452652052018502113737968204529790495739233258572209422774257139256367928649554562561889013164344608269555777150446651170697255381344437283003508476336814132594917061838422072660017477530465048729471603537912401826065081663165440462979219418291010867656746870617893935758241591032350010782861988742885918015532494020406350897048575155800941991107973433915573030255070411073793489218782862225921465295055907689734413881263179029741870520797816282420230090879687287575328294171448819803530205292587159921154471289747571107461754730577787617451127061265552788125691266357724955508391085485034126227212788895416902189479587194999818764639403752596165043883295506465916277734482380252399557395621566461322664559344483889187037851178431011220134914560438657522787409632677020269086895142488669203469256629173438313487046130238010206678820035631793666627274457756812810094004185303422637897314225624079032617334487815628021058997628511963565055629435278956251869329025544623291223984190562109149316159243565323565271491356378189561005084676592786453581431393651385181326525455441155960432946682976515756161038293313433862078763004704003356983371787414787104076401121444383911561
# _c = 305937839546594439230463861584604201077374759167468410827830943528403007941779658881672477705113617614828611332427199124217887937391378281943856159571057598203709366891547401974326016980711130197275312149966105151573748299654404630150641461765232935912266448303266990247145252052886920248198006212876273661195636104435277145396636985516064154534488750879453474211852461463041960835745695368577903786702607508492658563272121038693371752289017330781719235752018697635304458321008407930986565779826278048082764754367267460637798512780153281325733348999426407049795270044819657399403071013496169060640127279409914638535996355848933378734045908205536540619564723586905257569498716707820544351092379516465943537383422680357333849248129118148543389733395686399565999586899123087310025442994131218237679518267106194962305629529210402269726736072967966518381350920965727690274018080619332676536005722214955949897632990356174168234408837737546230730400434240785496100281815168806724358191550743656843853383646410487436540166360406982096949178466861150173527305369007546917550634679211293496458282787881244581230558011582720632502886494712233308474151958909251857281750741736910202763888790654287328846201724930302778996046434656839999091303411

通过_e求出t。观察u = getPrime(bit / 4 - num)可知 $u<_n^{\dfrac{1}{4}}$,可以尝试用Wienner Attack分解_n,然后求出e1

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
37
38
from Crypto.Util.number import *
from Crypto.Cipher import DES
from gmpy2 import iroot

key = "abcdefgh".encode()

def des_decrypt(c):
des = DES.new(key, DES.MODE_ECB)
res = des.decrypt(c)
return res

n = 440489238264900860776949063845200558734341182253911040104689726634414488997095518284964514078079911856352824174173937251558842251349762631716798307360995414545464514355957499460396352456341058329671470384493547042182238690727766731554287411757022792467324815342497916894285866240516524768645049867582541899123632009100512965460004548382054578461249990158442675234477122521189649316341623637146867589119951831385717513964941787562068891523060843170463600255518728070958509224053460041184869943038887434435024428311063533345514827827485121055022245800823723487812635502090530820946638405345755666124356919178290008475459419571761406117827422883820901663916276191422633940699113760516149002609672230610575442643822241126824287790055264162725209120192661985259423924307785452001927701323647247782658775780117642900694831475681037634691806232211286493187121464506122012889644137364079403183353774265910554863733455161820449073656744610495110838881353269890437984975607744603113572453211439334880155671730821755361054781243639407912133971530394031933785051770725331242932929244719594830548310768937037042243794551163891451545574837838357398072638709907958216067999891842395376953596940377457308329336524488962532620850237570279134567668379
e = 861605654852236668414010386016782729745549477722901970933220380452652052018502113737968204529790495739233258572209422774257139256367928649554562561889013164344608269555777150446651170697255381344437283003508476336814132594917061838422072660017477530465048729471603537912401826065081663165440462979219418291010867656746870617893935758241591032350010782861988742885918015532494020406350897048575155800941991107973433915573030255070411073793489218782862225921465295055907689734413881263179029741870520797816282420230090879687287575328294171448819803530205292587159921154471289747571107461754730577787617451127061265552788125691266357724955508391085485034126227212788895416902189479587194999818764639403752596165043883295506465916277734482380252399557395621566461322664559344483889187037851178431011220134914560438657522787409632677020269086895142488669203469256629173438313487046130238010206678820035631793666627274457756812810094004185303422637897314225624079032617334487815628021058997628511963565055629435278956251869329025544623291223984190562109149316159243565323565271491356378189561005084676592786453581431393651385181326525455441155960432946682976515756161038293313433862078763004704003356983371787414787104076401121444383911561
c = 305937839546594439230463861584604201077374759167468410827830943528403007941779658881672477705113617614828611332427199124217887937391378281943856159571057598203709366891547401974326016980711130197275312149966105151573748299654404630150641461765232935912266448303266990247145252052886920248198006212876273661195636104435277145396636985516064154534488750879453474211852461463041960835745695368577903786702607508492658563272121038693371752289017330781719235752018697635304458321008407930986565779826278048082764754367267460637798512780153281325733348999426407049795270044819657399403071013496169060640127279409914638535996355848933378734045908205536540619564723586905257569498716707820544351092379516465943537383422680357333849248129118148543389733395686399565999586899123087310025442994131218237679518267106194962305629529210402269726736072967966518381350920965727690274018080619332676536005722214955949897632990356174168234408837737546230730400434240785496100281815168806724358191550743656843853383646410487436540166360406982096949178466861150173527305369007546917550634679211293496458282787881244581230558011582720632502886494712233308474151958909251857281750741736910202763888790654287328846201724930302778996046434656839999091303411

t = bytes_to_long(des_decrypt(long_to_bytes(e)))

def wienerAttack(_e, _n):
con_frac = continued_fraction(_e / _n)
conv = con_frac.convergents()
for _ in conv:
k, dg = _.numerator(), _.denominator()
if k == 0 or dg == 0:
continue
_phi = _e * dg // k
if (_n - _phi + 1) % 2 == 0 and iroot(abs(pow((_n - _phi + 1) // 2, 2) - _n), 2)[1]:
delta = (_phi - _n - 1) ** 2 - 4 * _n
_p = (_n + 1 - _phi - int(iroot(delta, 2)[0])) // 2
_q = _n // _p
assert _n % _q == 0
return _p, _q

p, q = wienerAttack(t, n)
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)
e1 = pow(c, d, n)
print(f'e1 = {e1}')
#e1 = 114552459553730357961013268333698879659007919035942930313432809776799669181481660306531243618160127922304264986001501784564575128319884991774542682853466808329973362019677284072646678280051091964555611220961719302320547405880386113519147076299481594997799884384012548506240748042365643212774215730304047871679706035596550898944580314923260982768858133395187777029914150064371998328788068888440803565964567662563652062845388379897799506439389461619422933318625765603423604615137217375612091221578339493263160670355032898186792479034771118678394464854413824347305505135625135428816394053078365603937337271798774138959

这里需要参考论文(Extending Wiener’s Attack in the Presence of Many Decrypting Exponents),利用e1,e2分解N

根据论文中,结合WienerGuo的想法。

令$λ(N)=(p − 1)(q − 1)/g$ , $s = 1 − p − q$,按题意有
$$
\begin{cases}
e_1d_1 = 1\quad mod\ λ(N)\\
e_2d_2 = 1\quad mod\ λ(N)
\end{cases}
==>
\begin{cases}
e_1d_1 = 1+k_1λ(N)\\
e_2d_2 = 1+k_2λ(N)
\end{cases}
$$
根据Wiener的想法,有等式
$$
\begin{cases}
e_1d_1g−k_1N=g+k_1s\\
e_2d_2g − k_2N = g+k_2s
\end{cases}\tag{1}
$$
根据Guo的想法,有等式(上面的式子做变换)
$$
k_1e_2d_2 − k_2d_1e_1 = k_1 − k_2\tag{2}
$$
由(1)(2)可得 (第三个等式由(1)中两个式子相乘的来的)
$$
\begin{cases}
e_1d_1g − k_1N = g + k_1s\\
k_1e_2d_2 − k_2d_1e_1 = k_1 − k_2\\
d_1d_2g^2e_1e_2 − d_1gk_2e_1N − d_2gk_1e_2N + k_1k_2N_2 = (g + k_1s)(g + k_2s)
\end{cases}
$$
转换成矩阵方程($k_1k_2$拿来凑方阵)
$$
A = [k_1k_2, d_1gk_2, d_2gk_1, d_1d_2g_2]
$$

$$
L = \left[
\matrix{
1 & −N & 0 & N^2\\
& e_1 & −e_1 & −e_1N\\
& & e_2 & −e_2N\\
& & &e_1e_2
}
\right]
$$

$$
B=[k_1k_2, k_2(g + k_1s), g(k_1 − k_2),(g + k_1s)(g + k_2s)]
$$

$$
A×L=B
$$

如果B是L的最短向量,可以通过LLL算法求出B,但是上式并不满足Minkowoski’s first theorem(啊吧啊吧),需要进行调整。

令$M_1=N^{1/2}$,$M_2=N^{1+α}$ (其中$α<5/14$)
$$
L_2 = \left[
\matrix{
N & −M_1N & 0 & N^2\\
& M_1e_1 & −M_2e_1 & −e_1N\\
& & M_2e_2 & −e_2N\\
& & &e_1e_2
}
\right]
$$
$$
B_2=[k_1k_2N, k_2(g + k_1s)M_1, g(k_1 − k_2)M_2,(g + k_1s)(g + k_2s)]
$$

$$
A×L_2=B_2
$$

然后对$L_2$进行LLL求出B,解矩阵方程求出A,然后
$$
\dfrac{e_1×A[1]}{A[0]}=\dfrac{e_1d_1gk_2}{k_1k_2}=\dfrac{k_1φ(N)+g}{k_1}=φ(N)+\dfrac{g}{k_1}≈φ(N)
$$

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
#sage
from Crypto.Util.number import long_to_bytes
import gmpy2
N = 14922959775784066499316528935316325825140011208871830627653191549546959775167708525042423039865322548420928571524120743831693550123563493981797950912895893476200447083386549353336086899064921878582074346791320104106139965010480614879592357793053342577850761108944086318475849882440272688246818022209356852924215237481460229377544297224983887026669222885987323082324044645883070916243439521809702674295469253723616677245762242494478587807402688474176102093482019417118703747411862420536240611089529331148684440513934609412884941091651594861530606086982174862461739604705354416587503836130151492937714365614194583664241
e1 = 114552459553730357961013268333698879659007919035942930313432809776799669181481660306531243618160127922304264986001501784564575128319884991774542682853466808329973362019677284072646678280051091964555611220961719302320547405880386113519147076299481594997799884384012548506240748042365643212774215730304047871679706035596550898944580314923260982768858133395187777029914150064371998328788068888440803565964567662563652062845388379897799506439389461619422933318625765603423604615137217375612091221578339493263160670355032898186792479034771118678394464854413824347305505135625135428816394053078365603937337271798774138959
e2 = 27188825731727584656624712988703151030126350536157477591935558508817722580343689565924329442151239649607993377452763119541243174650065563589438911911135278704499670302489754540301886312489410648471922645773506837251600244109619850141762795901696503387880058658061490595034281884089265487336373011424883404499124002441860870291233875045675212355287622948427109362925199018383535259913549859747158348931847041907910313465531703810313472674435425886505383646969400166213185676876969805238803587967334447878968225219769481841748776108219650785975942208190380614555719233460250841332020054797811415069533137170950762289
c = 6472367338832635906896423990323542537663849304314171581554107495210830026660211696089062916158894195561723047864604633460433867838687338370676287160274165915800235253640690510046066541445140501917731026596427080558567366267665887665459901724487706983166070740324307268574128474775026837827907818762764766069631267853742422247229582756256253175941899099898884656334598790711379305490419932664114615010382094572854799421891622789614614720442708271653376485660139560819668239118588069312179293488684403404385715780406937817124588773689921642802703005341324008483201528345805611493251791950304129082313093168732415486813
for i in range(1000):
alpha2 = i/1000
M1 = int(gmpy2.mpz(N)**0.5)
M2 = int( gmpy2.mpz(N)**(1+alpha2) )
D = diagonal_matrix(ZZ, [N, M1, M2, 1])
B = Matrix(ZZ, [ [1, -N, 0, N**2],
[0, e1, -e1, -e1*N],
[0, 0, e2, -e2*N],
[0, 0, 0, e1*e2] ]) * D
L = B.LLL()
v = Matrix(ZZ, L[0])
x = v * B**(-1)
phi = (x[0,1]/x[0,0]*e1).floor()
try:
d = inverse_mod( 65537, phi)
m = long_to_bytes(power_mod(c, d, N))
if b'GWHT' in m or b'flag' in m:
print(i)
print(m)
break
except:
pass


参考:

Extending Wiener’s Attack in the Presence of Many Decrypting Exponents

RSA | Lazzaro (lazzzaro.github.io)

Wiener’s Attack | 4XWi11’s Blog


羊城杯-2020-Simple
http://example.com/2022/08/20/CTF/[羊城杯 2020]Simple/
作者
gla2xy
发布于
2022年8月20日
许可协议