0%

2024-春秋杯网络安全联赛夏季赛-wp-crypto

还是写写吧。

ezzzecc

题目描述:

1
ECC罢了

题目:

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
p = getPrime(256)
a = getPrime(256)
b = getPrime(256)
E = EllipticCurve(GF(p),[a,b])
m = E.random_point()
G = E.random_point()
k = getPrime(18)
K = k * G
r = getPrime(256)
c1 = m + r * K

c2 = r * G

cipher_left = s2n(flag[:len(flag)//2]) * m[0] #flag的前半部分乘m[0],所以只要用密文的除于m[0]即可得到flag前半部分
cipher_right = s2n(flag[len(flag)//2:]) * m[1] #flag的后半部分点乘m[1]


p = koZP3YQAklARRNrmYfjxoKIAXegOcG4jMOmKb08uESOkCCn72d6UM2NWgefYPEMq4EJ1M0jKaqt02Guo5Ubccjqg4QZaaHbScREx38UMLQKwG0LcDd8VFX1zkobc1ZQn4L3DhKQrgJZI55todgOdJuHN532bxScAvOF26gJyQclPtRHn3M6SHrRCEXzzmszd68PJlLB6HaabrRrCW9ZoAYSZetM5jDBtNCJLpR0CBZUUk3Oeh2MZQu2vk8DZ1QqNG49hlxGfawp1FXvAZPdMwixzkhEQnbCDcOKzYyT6BZF2Dfd940tazl7HNOswuIpLsqXQ2h56guGngMeYfMXEZV09fsB3TE0N934CLF8TbZnzFzEkOe8TPTK2mWPVSrgmbsGHnxgYWhaRQWg3yosgDfrEa5qfVl9De41PVtTw024gltovypMXK5XMhuhogs0EMN7hkLapLn6lMj
p的格式为p={p}

a = 87425770561190618633288232353256495656281438408946725202136726983601884085917
b = 107879772066707091306779801409109036008421651378615140327877558014536331974777
K = (49293150360761418309411209621405185437426003792008480206387047056777011104939 : 43598371886286324285673726736628847559547403221353820773139325027318579443479)
G = (34031022567935512558184471533035716554557378321289293120392294258731566673565 : 74331715224220154299708533566163247663094029276428146274456519014761122295496)
私钥k小于1000000
c1 = (3315847183153421424358678117707706758962521458183324187760613108746362414091 : 61422809633368910312843316855658127170184420570309973276760547643460231548014)
c2 = (12838481482175070256758359669437500951915904121998959094172291545942862161864 : 60841550842604234546787351747017749679783606696419878692095419214989669624971)
cipher_left = 75142205156781095042041227504637709079517729950375899059488581605798510465939
cipher_right = 61560856815190247060747741878070276409743228362585436028144398174723191051815

随机生成一条椭圆曲线:

并随机取两点m、G,之后随机生成18bit的k和256bit的r,并计算:

给出a、b、K、G、c1、c2,求出m点的坐标就可以简单运算得到flag。

这就是最基础的ECC的加密方案,私钥k由于只有18bit,所以可以爆破求出来。唯一一点在于p以如下方式给了出来:

1
koZP3YQAklARRNrmYfjxoKIAXegOcG4jMOmKb08uESOkCCn72d6UM2NWgefYPEMq4EJ1M0jKaqt02Guo5Ubccjqg4QZaaHbScREx38UMLQKwG0LcDd8VFX1zkobc1ZQn4L3DhKQrgJZI55todgOdJuHN532bxScAvOF26gJyQclPtRHn3M6SHrRCEXzzmszd68PJlLB6HaabrRrCW9ZoAYSZetM5jDBtNCJLpR0CBZUUk3Oeh2MZQu2vk8DZ1QqNG49hlxGfawp1FXvAZPdMwixzkhEQnbCDcOKzYyT6BZF2Dfd940tazl7HNOswuIpLsqXQ2h56guGngMeYfMXEZV09fsB3TE0N934CLF8TbZnzFzEkOe8TPTK2mWPVSrgmbsGHnxgYWhaRQWg3yosgDfrEa5qfVl9De41PVtTw024gltovypMXK5XMhuhogs0EMN7hkLapLn6lMj

试了下base64解不出来能用的东西,然而由于给定了曲线上的四个点,所以任取其中两个,就有:

所以求GCD再去除点小因子就可以得到p了。

由于足足给了四个点,所以不给a、b也都可以

还有一个小技巧就是用累加来做爆破会显著提速,可以避免重复计算很多倍点。这个技巧在上一次春秋杯的wp中也用到过:

2023-春秋杯网络安全联赛冬季赛-wp-crypto | 糖醋小鸡块的blog (tangcuxiaojikuai.xyz)

exp:

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
from Crypto.Util.number import *
from tqdm import *

a = 87425770561190618633288232353256495656281438408946725202136726983601884085917
b = 107879772066707091306779801409109036008421651378615140327877558014536331974777
K = (49293150360761418309411209621405185437426003792008480206387047056777011104939 , 43598371886286324285673726736628847559547403221353820773139325027318579443479)
G = (34031022567935512558184471533035716554557378321289293120392294258731566673565 , 74331715224220154299708533566163247663094029276428146274456519014761122295496)
c1 = (3315847183153421424358678117707706758962521458183324187760613108746362414091 , 61422809633368910312843316855658127170184420570309973276760547643460231548014)
c2 = (12838481482175070256758359669437500951915904121998959094172291545942862161864 , 60841550842604234546787351747017749679783606696419878692095419214989669624971)
cipher_left = 75142205156781095042041227504637709079517729950375899059488581605798510465939
cipher_right = 61560856815190247060747741878070276409743228362585436028144398174723191051815

p = GCD((K[1]^2 - K[0]^3 - a*K[0] - b) , (G[1]^2 - G[0]^3 - a*G[0] - b))
E = EllipticCurve(GF(p),[a,b])
K = E(K)
G = E(G)
c1 = E(c1)
c2 = E(c2)

base = G
for i in trange(2,1000000):
base += G
if(base == K):
k = i
break
assert K == k*G

m = c1 - c2*k
print(m)
flag1 = long_to_bytes(int(cipher_left // m[0]))
flag2 = long_to_bytes(int(cipher_right // m[1]))
print(flag1 + flag2)


#flag{2d6a7e4e-02d3-11ef-8836-a4b1c1c5a2d2}



happy2024

题目描述:

1
2024加油

题目:

happy2024.py:

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
from not2022but2024 import CBC_key
from Crypto.Util.Padding import pad

flag = b'flag{}'
from Crypto.Cipher import AES
from hashlib import sha256
import random

n = 31
m = 80
M = random_prime(2^256)
As = [random.randrange(0,M) for i in range(n)]
xs = [random_vector(GF(2),m).change_ring(ZZ) for i in range(n)]
Bs = sum([As[_] * vector(Zmod(M),xs[_]) for _ in range(n)]).change_ring(ZZ)

IV = sha256(str(int(sum(As))).encode()).digest()[:16]
aes = AES.new(CBC_key,AES.MODE_CBC,iv=IV)
cipher = aes.encrypt(pad(flag,16))
print(cipher)
print(Bs)
print(M)

"""
b'%\x97\xf77\x16.\x83\x99\x06^\xf2h!k\xfaN6\xb0\x19vd]\x04B\x9e&\xc1V\xed\xa3\x08gX\xb2\xe3\x16\xc2y\xf5/\xb1\x1f>\xa1\xa0DO\xc6gy\xf2l\x1e\xe89\xaeU\xf7\x9d\x03\xe5\xcd*{'
(53844623749876439509532172750379183740225057481025870998212640851346598787721, 15997635878191801541643082619079049731736272496140550575431063625353775764393, 8139290345909123114252159496175044671899453388367371373602143061626515782577, 51711312485200750691269670849294877329277547032926376477569648356272564451730, 56779019321370476268059887897332998945445828655471373308510004694849181121902, 11921919583304047088765439181178800943487721824857435095500693388968302784145, 41777099661730437699539865937556780791076847595852026437683411014342825707752, 68066063799186134662272840678071052963223888567046888486717443388472263597588, 62347360130131268176184039659663746274596563636698473727487875097532115406559, 5552427086805474558842754960080936702720391900282118962928327391068474712240, 48174546926340119542515098715425118344495523250058429245324464327285482535849, 8793683612853105242264232876135147970346410658466322451040541263235700009570, 78872313670499828088921565348302137515276635926740431961166334829533274321063, 45986964918902932699857479987521822871519141147943250535680974229322816549720, 5539445840707805914548390575494054384665037598195811353312773359759245783130, 20826977782899762485848762121688687172338304931446040988601154085704702880401, 46412211529487215742337744878389285037116176985579657423264681199244501574725, 50741521861819713251561088062479658512988690918747542471827101566427731303416, 2657362476409491643067267745198536051013594201408763262228104521443406410606, 44328850588851214219220815931558890597249087261312360172796979417041192180750, 17240480010040498121198897919561403023278264974274103780966819232080038065027, 76464770903606818697905572779761942703446600798395362596698226797476804541350, 68085613496380272855135907856973365357126900379731050931749074863934645465000, 9526872466819179025323613184178423510032119770349155497772862700507205270355, 28561337010953007345414455535991538568670238712225998300322929406204673707677, 39182834208152122329027105134597748924433413223238510660062164011424607149326, 19600894094417831727934201861135428039216930531542618497625138063955073257655, 33328666355366104030800248593757531247937582259417117239494927842284231531315, 27309478993506749161736165865367616487993717640890015043768259212155864131357, 32466044572968154084881296026899630667525833604042642990295342316076396001186, 49980145403553319854613749104421978583845098879328180142454823188167202440531, 38902032967058543060885229430655776526806612465844770409338358289020456837934, 78745490507168848644435092323691842070096557975478968062804777954092505226481, 29262215059225133132435433010691828148944958395141222387754208495595513295896, 6511387460586172200641169204557875679554320457409786241141816573577911255491, 66384481485687195909117407019475796131750762463683904604078327730810293442381, 423759905526048383541413041558602466949757468395447771021215945027193456079, 22783408973585275782090957855992582495700723663661365548067357177569979041893, 68353193576625297253561095680880135893826094396013897100461325445097220567952, 43167069172003777333498030236780725018297276760410131777676641770086016833895, 64358541048274393300028483577573557871346089755363306971761786692679519831483, 21556895066359380729591004278007242407987861350911480029337345312081293559522, 44577165826706395273335181181407938788716768576602201516787959082367484270939, 78757778436852423927977028333940102206341452120720821559562765928972163293676, 44086875063535769349025637423479101247594814134304419072849625465484225865969, 14807706619359620049095657244485266549982349493285112282927264862821502986777, 43450687889967222089875050731849984583914520350091026482076939962301357700844, 1474778474197964170746922000689413626959960404877093741742022788928758658052, 79005121352540562329295808987757987563818908122338120731119811866179839023066, 47361429831079185336051370209844150786334814579472466274050224935364333043476, 8909641306798261411104006708035991379862284048887418817598377473145077145642, 44993528669446910461207972446344484798499156885515181685694150462051560323869, 60204243272925546012169935228277233636280408169577344559847112958669050860101, 66809206609934431859673802937592425152676610053648406215573441926481740948749, 48623757302381792245138496825183044619235050623516633984941208604059757210728, 74934019261870654132458355068539987475536823529848461398042458398130801089348, 81278897734052917585963333108338812132716202790194259021265555401046891572210, 41418370274745377550600009352057265922713132669834032188979684042175922204024, 73981010754794931896065529724613353453372905938901875720094092383581574259191, 11510558496830929812186594415924901190526760075439658941646537744390447056913, 12871197940932509721689273944282764851472299179520294551038550766143300003239, 13125880938267970248643653453332470640527994428672724309079849030361661332656, 54395419708886945822916038876690794705789028459055268227222784885329659953982, 61086065362549289820758257234061183781820530343096737751500151263095654158833, 82468574289042215923908109910435173164917593677419944115441863191433795206895, 74824772928304750096519403623184368585460834399443013973554958461695733158569, 62083272769549467370505302454770858941632031970595402929903886003242570089639, 32887658447648473554892464271221330218759930615421257444587260809741011575629, 61429802749826163386356730793012182546392982886506956044525858721859869425131, 5026334434650853992374810127604777276035123569907012144091150436739161826287, 45670628392162402176230172863069957038704667046592086395237022845943911838596, 75520245720261510582172547313413372786802547571090110489287163846652239401646, 58965653594414801363386215405590061806834352303047020261264473838037335631061, 58420763657138617301836404602193276258504426799372302098717637069900583548539, 59706321905964570794806865247363209194143775670139452625484601579677510881069, 58198559234141523043769073193017418608700536234755760366044515212056701655389, 63604949023865770163110419193113341020042474142600282131130750460724114084001, 83394429495100363085521124642271430199140318544724150468993097819105267094727, 69274794456073656789648159458959148992942789823222968847070524400609637893875, 46951397339712109206750633799342393646147684284310708226074432825222250739146)
83509079445737370227053838831594083102898723557726396235563637483818348136543
"""

not2022but2024.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from Crypto.Util.number import *

CBC_key = b''

p,q = getPrime(512),getPrime(512)
n = p * q
N = n**2 + 2024
hint = (pow(3, 2022, N) * p**2 + pow(5, 2022, N) * q**2) % N
c = pow(bytes_to_long(CBC_key), 65537, n)

print('n =', n)
print('h =', hint)
print('c =', c)

'''
n = 104765768221225848380273603921218042896496091723683489832860494733817042387427987244507704052637674086899990536096984680534816330245712225302233334574349506189442333792630084535988347790345154447062755551340749218034086168589615547612330724516560147636445207363257849894676399157463355106007051823518400959497
h = 7203581190271819534576999256270240265858103390821370416379729376339409213191307296184376071456158994788217095325108037303267364174843305521536186849697944281211331950784736288318928189952361923036335642517461830877284034872063160219932835448208223363251605926402262620849157639653619475171619832019229733872640947057355464330411604345531944267500361035919621717525840267577958327357608976854255222991975382510311241178822169596614192650544883130279553265361702184320269130307457859444687753108345652674084307125199795884106515943296997989031669214605935426245922567625294388093837315021593478776527614942368270286385
c = 86362463246536854074326339688321361763048758911466531912202673672708237653371439192187048224837915338789792530365728395528053853409289475258767985600884209642922711705487919620655525967504514849941809227844374505134264182900183853244590113062802667305254224702526621210482746686566770681208335492189720633162
'''

flag最终通过AES-CBC加密,题目的两个文件分别对应key和iv,需要分别求解出来来解最后的AES。

CBC_key

题目随机生成512bit的素数p、q,计算其乘积为n,然后额外给出以下两个值:

然后用n当作公钥加密了CBC_key,需要恢复私钥p、q才能解密。

看到hint的式子,第一反应就是p、q在模N下实在显得太小了,并且其实p^2、q^2也显得很小(只有N的一半数量级那么大),所以可以造格求解。而就把上面的模等式化为等式,就得到了造格的依据:

造出以下格:

这个格具有的线性关系是:

然后把最后一列配上大系数保证规约出0,并且第三列配平一下,理论上来说应该就行了。

然而实际规约会发现,LLL出来的向量比p^2、q^2要略小一点,也就是规约出来的向量是如下形式的(其中1023大约就是p^2的数量级,为了配平):

然而由于只是略小一点,所以可以在小范围内爆破一下LLL之后向量的线性组合,由于这些组合后的向量其实也是格中向量,就有机会找到目标向量$(p^2,q^2,1,0)$了。

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
L = Matrix(ZZ,[
[1,0,0,3^2022],
[0,1,0,5^2022],
[0,0,2^1022,-h],
[0,0,0,N]
])
L[:,-1:] *= N
res = L.LLL()


import gmpy2
t = 0
for i in range(-100,100):
for j in range(-100,100):
for k in range(-100,100):
t = i*res[0] + j*res[1] + k*res[2]
if(gmpy2.iroot(abs(t[0]),2)[1] == True):
pp = gmpy2.iroot(abs(t[0]),2)[0]
p = GCD(pp,n)
q = n // p
print(p*q == n , p)

此外,hint对应的等式其实很自然就会联想到copper,因为这其实就是以p、q为小根的多项式,并且次数仅有二次。但是直接把这个等式放进来去二元copper会发现一个报错:

1
ZeroDivisionError: inverse of Mod(..., ...) does not exist

这个错误其实是在处理高次项系数时,系数模N的逆不存在导致的,求一下GCD会发现N中含有3,所以和3^2022不互素。处理方式也很简单,把N除以3之后就互素了。然后就是上界似乎有点不够,所以简单爆破一位即可。

exp:

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
from Crypto.Util.number import *
import itertools

def small_roots(f, bounds, m=1, d=None):
if not d:
d = f.degree()

R = f.base_ring()
N = R.cardinality()

f /= f.coefficients().pop(0)
f = f.change_ring(ZZ)

G = Sequence([], f.parent())
for i in range(m+1):
base = N^(m-i) * f^i
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g)

B, monomials = G.coefficient_matrix()
monomials = vector(monomials)

factors = [monomial(*bounds) for monomial in monomials]
for i, factor in enumerate(factors):
B.rescale_col(i, factor)

B = B.dense_matrix().LLL()

B = B.change_ring(QQ)
for i, factor in enumerate(factors):
B.rescale_col(i, 1/factor)

H = Sequence([], f.parent().change_ring(QQ))
for h in filter(None, B*monomials):
H.append(h)
I = H.ideal()
if I.dimension() == -1:
H.pop()
elif I.dimension() == 0:
roots = []
for root in I.variety(ring=ZZ):
root = tuple(R(root[var]) for var in f.variables())
roots.append(root)
return roots

return []

n = 104765768221225848380273603921218042896496091723683489832860494733817042387427987244507704052637674086899990536096984680534816330245712225302233334574349506189442333792630084535988347790345154447062755551340749218034086168589615547612330724516560147636445207363257849894676399157463355106007051823518400959497
h = 7203581190271819534576999256270240265858103390821370416379729376339409213191307296184376071456158994788217095325108037303267364174843305521536186849697944281211331950784736288318928189952361923036335642517461830877284034872063160219932835448208223363251605926402262620849157639653619475171619832019229733872640947057355464330411604345531944267500361035919621717525840267577958327357608976854255222991975382510311241178822169596614192650544883130279553265361702184320269130307457859444687753108345652674084307125199795884106515943296997989031669214605935426245922567625294388093837315021593478776527614942368270286385
c = 86362463246536854074326339688321361763048758911466531912202673672708237653371439192187048224837915338789792530365728395528053853409289475258767985600884209642922711705487919620655525967504514849941809227844374505134264182900183853244590113062802667305254224702526621210482746686566770681208335492189720633162
N = n**2 + 2024
N = N // 3


PR.<pl,ql> = PolynomialRing(Zmod(N))
for i in [1,3]:
for j in [1,3]:
f = 3^2022*(2^511 + 4*pl + i)^2 + 5^2022*(2^511 + 4*ql + j)^2 - h
res = small_roots(f,(2^509,2^509),m=1,d=3)
if(res != []):
p = int(2^511 + 4*int(res[0][0]) + i)
q = n // p
if(p*q == n):
CBC_key = long_to_bytes(pow(c,inverse(65537,(p-1)*(q-1)),n))
print(CBC_key)


#mylove_in_summer


IV

第二部分给出了一个等式:

其中x是01矩阵。

题目用A的sum作sha256得到了IV,并且整个式子只给出B和M,要求还原A。

这是个hssp问题,是经典的正交格的应用,其大致思路可以参考一下下面这篇的Lattice和crys:

Crypto趣题-Lattice | 糖醋小鸡块的blog (tangcuxiaojikuai.xyz)

然而在做hssp的时候会有一个问题,就是对核空间的向量进行规约后,会发现得到的大多是由$(0,1,-1)$组成的向量,而并非预期的01向量,这是因为在规约过程中向量之间互相在约减导致的。而针对这个问题论文提供了两个思路:

image-20240707171204543

而实际上测试发现后一种效果似乎要更好一些,实现也很简单,就是对核空间规约的向量反复进行线性组合,一直到找到全部01向量为止。

如此就可以恢复出整个x了,然后解矩阵方程就可以得到A,求和并作哈希就有IV了。

exp:

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
56
57
58
from Crypto.Util.number import *

#Zmod(M): xA = B (x is binary Matrix)
B = (53844623749876439509532172750379183740225057481025870998212640851346598787721, 15997635878191801541643082619079049731736272496140550575431063625353775764393, 8139290345909123114252159496175044671899453388367371373602143061626515782577, 51711312485200750691269670849294877329277547032926376477569648356272564451730, 56779019321370476268059887897332998945445828655471373308510004694849181121902, 11921919583304047088765439181178800943487721824857435095500693388968302784145, 41777099661730437699539865937556780791076847595852026437683411014342825707752, 68066063799186134662272840678071052963223888567046888486717443388472263597588, 62347360130131268176184039659663746274596563636698473727487875097532115406559, 5552427086805474558842754960080936702720391900282118962928327391068474712240, 48174546926340119542515098715425118344495523250058429245324464327285482535849, 8793683612853105242264232876135147970346410658466322451040541263235700009570, 78872313670499828088921565348302137515276635926740431961166334829533274321063, 45986964918902932699857479987521822871519141147943250535680974229322816549720, 5539445840707805914548390575494054384665037598195811353312773359759245783130, 20826977782899762485848762121688687172338304931446040988601154085704702880401, 46412211529487215742337744878389285037116176985579657423264681199244501574725, 50741521861819713251561088062479658512988690918747542471827101566427731303416, 2657362476409491643067267745198536051013594201408763262228104521443406410606, 44328850588851214219220815931558890597249087261312360172796979417041192180750, 17240480010040498121198897919561403023278264974274103780966819232080038065027, 76464770903606818697905572779761942703446600798395362596698226797476804541350, 68085613496380272855135907856973365357126900379731050931749074863934645465000, 9526872466819179025323613184178423510032119770349155497772862700507205270355, 28561337010953007345414455535991538568670238712225998300322929406204673707677, 39182834208152122329027105134597748924433413223238510660062164011424607149326, 19600894094417831727934201861135428039216930531542618497625138063955073257655, 33328666355366104030800248593757531247937582259417117239494927842284231531315, 27309478993506749161736165865367616487993717640890015043768259212155864131357, 32466044572968154084881296026899630667525833604042642990295342316076396001186, 49980145403553319854613749104421978583845098879328180142454823188167202440531, 38902032967058543060885229430655776526806612465844770409338358289020456837934, 78745490507168848644435092323691842070096557975478968062804777954092505226481, 29262215059225133132435433010691828148944958395141222387754208495595513295896, 6511387460586172200641169204557875679554320457409786241141816573577911255491, 66384481485687195909117407019475796131750762463683904604078327730810293442381, 423759905526048383541413041558602466949757468395447771021215945027193456079, 22783408973585275782090957855992582495700723663661365548067357177569979041893, 68353193576625297253561095680880135893826094396013897100461325445097220567952, 43167069172003777333498030236780725018297276760410131777676641770086016833895, 64358541048274393300028483577573557871346089755363306971761786692679519831483, 21556895066359380729591004278007242407987861350911480029337345312081293559522, 44577165826706395273335181181407938788716768576602201516787959082367484270939, 78757778436852423927977028333940102206341452120720821559562765928972163293676, 44086875063535769349025637423479101247594814134304419072849625465484225865969, 14807706619359620049095657244485266549982349493285112282927264862821502986777, 43450687889967222089875050731849984583914520350091026482076939962301357700844, 1474778474197964170746922000689413626959960404877093741742022788928758658052, 79005121352540562329295808987757987563818908122338120731119811866179839023066, 47361429831079185336051370209844150786334814579472466274050224935364333043476, 8909641306798261411104006708035991379862284048887418817598377473145077145642, 44993528669446910461207972446344484798499156885515181685694150462051560323869, 60204243272925546012169935228277233636280408169577344559847112958669050860101, 66809206609934431859673802937592425152676610053648406215573441926481740948749, 48623757302381792245138496825183044619235050623516633984941208604059757210728, 74934019261870654132458355068539987475536823529848461398042458398130801089348, 81278897734052917585963333108338812132716202790194259021265555401046891572210, 41418370274745377550600009352057265922713132669834032188979684042175922204024, 73981010754794931896065529724613353453372905938901875720094092383581574259191, 11510558496830929812186594415924901190526760075439658941646537744390447056913, 12871197940932509721689273944282764851472299179520294551038550766143300003239, 13125880938267970248643653453332470640527994428672724309079849030361661332656, 54395419708886945822916038876690794705789028459055268227222784885329659953982, 61086065362549289820758257234061183781820530343096737751500151263095654158833, 82468574289042215923908109910435173164917593677419944115441863191433795206895, 74824772928304750096519403623184368585460834399443013973554958461695733158569, 62083272769549467370505302454770858941632031970595402929903886003242570089639, 32887658447648473554892464271221330218759930615421257444587260809741011575629, 61429802749826163386356730793012182546392982886506956044525858721859869425131, 5026334434650853992374810127604777276035123569907012144091150436739161826287, 45670628392162402176230172863069957038704667046592086395237022845943911838596, 75520245720261510582172547313413372786802547571090110489287163846652239401646, 58965653594414801363386215405590061806834352303047020261264473838037335631061, 58420763657138617301836404602193276258504426799372302098717637069900583548539, 59706321905964570794806865247363209194143775670139452625484601579677510881069, 58198559234141523043769073193017418608700536234755760366044515212056701655389, 63604949023865770163110419193113341020042474142600282131130750460724114084001, 83394429495100363085521124642271430199140318544724150468993097819105267094727, 69274794456073656789648159458959148992942789823222968847070524400609637893875, 46951397339712109206750633799342393646147684284310708226074432825222250739146)
M = 83509079445737370227053838831594083102898723557726396235563637483818348136543
n = 31
m = 80

######################################### part1 solve Orthogonal Lattice of B
if(1):
BL = block_matrix(ZZ,[
[M,0],
[Matrix(ZZ,B).T,1]
])
OL = BL.LLL()
OL = Matrix(ZZ,OL[:m-n,1:])


######################################### part2 find kernel and reduce
Ker = OL.right_kernel().matrix()
Ker = Ker.BKZ()


######################################### part3 recover binary x(use greedy methods)
def check(v):
if(all(i == 1 or i == 0 for i in v)):
return v
elif(all(i == -1 or i == 0 for i in v)):
return -v

def find(Ker,x):
x = [i for i in ini]
while(1):
for vi in x:
for i in Ker:
xi1 = check(i + vi)
xi2 = check(i - vi)
if xi1 and xi1 not in x:
x.append(xi1)
if(len(x) == n):
return Matrix(ZZ,x)
if xi2 and xi2 not in x:
x.append(xi2)
if(len(x) == n):
return Matrix(ZZ,x)

ini = [check(vi) for vi in Ker if check(vi)]
x = find(Ker,ini)


######################################### part4 recover sum of A
A = x.solve_left(Matrix(Zmod(M),B))
sumA = sum(A[0].change_ring(ZZ))

print(sumA)


#1190342683523422755570459424048363591795982274808192123460316142044766104571627


解密

1
2
3
4
5
6
7
8
9
p = 11846999515401139806618780458482772585816656222161925595380112630854263318903047176862162285755281915011589524788709945023820217521669415569797208065004797
q = n // p
CBC_key = long_to_bytes(pow(c,inverse(65537,(p-1)*(q-1)),n))

aes = AES.new(CBC_key,AES.MODE_CBC,iv=IV)
flag = aes.decrypt(cipher)
print(flag)

#flag{2024_1s_a_G00d_year_My_b3st_w1shes_fOr_ctfers}



Signature

题目描述:

1
来签个名吧

题目:

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import os
import hashlib
from Crypto.Util.number import *
from Crypto.PublicKey import DSA
import random
def gen_proof_key():
password = 'happy_the_year_of_loong'
getin = ''
for i in password:
if random.randint(0, 1):
getin += i.lower()
else:
getin += i.upper()
ans = hashlib.sha256(getin.encode()).hexdigest()
return getin,ans

def gen_key():
pri = random.randint(2,q - 2)
pub = pow(g,pri,p)
return pri,pub

def sign(m,pri):
k = int(hashlib.md5(os.urandom(20)).hexdigest(),16)
H = int(hashlib.sha256(m).hexdigest(),16)
r = pow(g,k,p) % q
s = pow(k,-1,q) * (H + pri * r) % q
return r,s

def verify(pub,m,signature):
r,s = signature
if r <= 0 or r >= q or s <= 0 or s >= q:
return False
w = pow(s,-1,q)
H = int(hashlib.sha256(m).hexdigest(),16)
u1 = H * w % q
u2 = r * w % q
v = (pow(g,u1,p) * pow(pub,u2,p) % p) % q
return v == r

def login():
print('Hello sir,Plz login first')
menu = '''
1.sign
2.verify
3.get my key
'''
times = 8
while True:
print(menu)
if times < 0:
print('Timeout!')
return False
choice = int(input('>'))
if choice == 1:
name = input('Username:').encode()
if b'admin' in name:
print('Get out!')
return False
r,s = sign(name,pri)
print(f'This is your signature -- > {r},{s}')
times -= 1
elif choice == 2:
print('Sure,Plz input your signature')
print(pri)
r = int(input('r:'))
s = int(input('s:'))
if verify(pub,b'admin',(r,s)) == True:
print('login success!')
return True
else:
print('you are not admin')
return False
elif choice == 3:
print(f'Oh,your key is {(p,q,g)}')
getin,ans = gen_proof_key()
print(f'Your gift --> {ans[:6]}')
your_token = input('Plz input your token\n>')
if your_token != getin:
print('Get out!')
exit(0)

key = DSA.generate(1024)
p, q, g = key.p, key.q, key.g
pri, pub = gen_key()
if login() == False:
exit(0)
print(open('/flag','r').read())

DSA签名题,可以签名多次,但签名消息不能包含”admin”,如果能对”admin”验签通过就可以拿到flag。

又是多次签名,又是DSA,显然是要造格了。而且小量也很明显,就是只有128bit的k,所以设法规约出他应该就好。

然而由于验签里有一句:

1
print(pri)

所以直接对admin签名就行,甚至没有这个proof花时间。

exp:

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
56
57
from pwn import *
import hashlib
from Crypto.Util.number import *
from Crypto.PublicKey import DSA
from tqdm import *
from itertools import *

#context.log_level = 'debug'

def proof():
sh.recvuntil(b"gift --> ")
password = 'happy_the_year_of_loong'
prefix = sh.recvline().strip().decode()

for i in tqdm(product([0,1],repeat=len(password)),total=2**len(password)):
tt = ""
for j in range(len(i)):
if(i[j] == 1):
tt += password[j].lower()
else:
tt += password[j].upper()
ans = hashlib.sha256(tt.encode()).hexdigest()
if(ans[:6] == prefix):
print("Find")
sh.sendline(tt.encode())
return True

return False

def sign(m,pri):
k = int(hashlib.md5(os.urandom(20)).hexdigest(),16)
H = int(hashlib.sha256(m).hexdigest(),16)
r = pow(g,k,p) % q
s = pow(k,-1,q) * (H + pri * r) % q
return r,s

sh = remote("8.147.128.163",13364)
ans = proof()
assert ans == True

sh.sendline(b"3")
sh.recvuntil(b"Oh,your key is ")
p,q,g = eval(sh.recvline().strip().decode())
sh.sendline(b"2")
sh.recvuntil(b"Sure,Plz input your signature")
sh.recvline()
pri = int(sh.recvline().strip().decode())
r,s = sign(b"admin",pri)
sh.sendline(str(r).encode())
sh.sendline(str(s).encode())

sh.recvline()
sh.recvline()
print(sh.recvline())


#flag{7263242b-ed78-4b06-947f-a6d90e59735f}