目录
【简单】sign1n
【中等】ECC?
【困难】babyhash
【困难】babyhash_revenge
from Crypto.Util.number import *
flag = b'DAS'
flag = bytes_to_long(flag)
e = 0x10001
def gen_keys():
p = getPrime(1024)
q = getPrime(1024)
phi = (p-1)*(q-1)
d = inverse(e,phi)
n = p*q
print(f'n = {n}')
WHATF = (d ** 3 + 3) % phi
print(f'WHATF= {WHATF}')
return d, n, WHATF,phi
def easy_sign(n,d):
m = flag * pow(r,e**2+d**2,n) % n
print(m)
s = pow(m,d,n)
return s,m
def gift():
assert t > 0
gift = pow(r,t) - 1
#print(t)
print(isPrime(gift))
d,n,WHATF,phi = gen_keys()
gift()
sign,m = easy_sign(n,d)
print(f'sign = {sign}')
r,t先不管,看看已知条件
这里W-3跟phi位数一样,那么k的bits跟e^3bits一样,而且远小于phi,使用连分数思想
sign没什么用,就求m
m=pow(sign,e,n)
再考虑r,t。这里给出r^t-1是素数。
两种情况,
t=1,r-1是素数
t!=1,展开项中的r-1=1,另外一项为素数
这里题目要是说了t>1就更好签到了
r=2,后面就很好解flag
exp:
n = 17501785470905115084530641937586010443633001681612179692218171935474388105810758340844015368385708349722992595891293984847291588862799310921139505076364559140770828784719022502905431468825797666445114531707625227170492272392144861677408547696040355055483067831733807927267488677560035243230884564063878855983123740667214237638766779250729115967995715398679183680360515620300448887396447013941026492557540060990171678742387611013736894406804530109193638867704765955683067309269778890269186100476308998155078252336943147988308936856121869803970807195714727873626949774272831321358988667427984601788595656519292763705699
WHATF= 7550872408895903340469549867088737779221735042983487867888690747510707575208917229455135563614675077641314504029666714424242441219246566431788414277587183624484845351111624500646035107614221756706581150918776828118482092241867365644233950852801286481603893259029733993572417125002284605243126366683373762688802313288572798197775563793405251353957529601737375987762230223965539018597115373258092875512799931693493522478726661976059512568029782074142871019609980899851702029278565972205831732184397965899892253392769838212803823816067145737697311648549879049613081017925387808738647333178075446683195899683981412014732
1
sign = 12029865785359077271888851642408932941748698222400692402967271078485911077035193062225857653592806498565936667868784327397659271889359852555292426797695393591842279629975530499882434299824406229989496470187187565025826834367095435441393901750671657454855301104151016192695436071059013094114929109806658331209302942624722867961155156665675500638029626815869590842939369327466155186891537025880396861428410389552502395963071259114101340089657190695306100646728391832337848064478382298002033457224425654731106858054291015385823564302151351406917158392454536296555530524352049490745470215338669859669599380477470525863815
m=pow(sign,e,n)
(e**3*(WHATF-3)/n).n()
#1.21443548300099e14
phi=(WHATF*pow(e,3) - (3*e**3)-1) // 121443548300099
d=inverse(e,phi)
ff=(e**2+d**2)%phi
k=ZZ(pow(2,ff,n))
kk=inverse(k,n)
print(long_to_bytes(ZZ(m*kk %n)))
题目就不贴了,给了三个加密公钥e1,e2,e3然后用ECC加密得到三个点
给了gift=n*getPrime(1024)
要是见过groebner_basis()就很好解了
首先算a,b,在环上定义三个方程组(由三个点),然后在理想集求解groebner_basis(),得到a,b,n
gift = 10954621221812651197619957228527372749810730943802288293715079353550311138677754821746522832935330138708418986232770630995550582619687239759917418738050269898943719822278514605075330569827210725314869039623167495140328454254640051293396463956732280673238182897228775094614386379902845973838934549168736103799539422716766688822243954145073458283746306858717624769112552867126607212724068484647333634548047278790589999183913
C1 = (1206929895217993244310816423179846824808172528120308055773133254871707902120929022352908110998765937447485028662679732041, 652060368795242052052268674691241294013033011634464089331399905627588366001436638328894634036437584845563026979258880828)
C2 = (1819289899794579183151870678118089723240127083264590266958711858768481876209114055565064148870164568925012329554392844153, 1110245535005295568283994217305072930348872582935452177061131445872842458573911993488746144360725164302010081437373324551)
C3 = (1112175463080774353628562547288706975571507012326470665917118873336738873653792420189391867408691423887642725415133046354, 1820636035485820691083758790204536675748006232767111209985774382700260408550258280489088658228739971137550264759084468620)
R.=PolynomialRing(Zmod(gift))
Ideal([C1[0]^3+a*C1[0]+b-C1[1]^2,C2[0]^3+a*C2[0]+b-C2[1]^2,C3[0]^3+a*C3[0]+b-C3[1]^2]).groebner_basis()
[a + 6383454939215515141151308275756464378147341998868124849701666287931118728967033226489555343116783930020043447064021757870443190275344745221658277278096846919402186283335931329880274804317278840879511880105400148227288592654329031719888755699046101784104099741865444662504240509089508615358820602230534486420527588876985837918460253592556268354478308719338006099829036747790521589851108766488409474143802894481467371124474, b + 2061828487946313274444567336921027851992389239431896215882831043443098187273467324250117099919991128038110286667574268827149737102849843003427760947370452301720570966798422301991069233423052047573723017573811854447144591388611545295336479676711135093748524215062079916506134402329979650885359052525127585725226235274380415403877926132099800327766309604816799309017969361197829094471646886280677088152723532310326801778432, 1858284081017011776897142483530706248351014197676168270132930318711536519639284920939350511528325590655669305434894548271]
得到a,b,n之后就构造Zmod(n)的椭圆曲线。
给了三个e,共模攻击,通过gcd发现e1,e3,gcd(e1,e3)=1
还别说,后面的部分还就是这么简单
a=-6383454939215515141151308275756464378147341998868124849701666287931118728967033226489555343116783930020043447064021757870443190275344745221658277278096846919402186283335931329880274804317278840879511880105400148227288592654329031719888755699046101784104099741865444662504240509089508615358820602230534486420527588876985837918460253592556268354478308719338006099829036747790521589851108766488409474143802894481467371124474
b=-2061828487946313274444567336921027851992389239431896215882831043443098187273467324250117099919991128038110286667574268827149737102849843003427760947370452301720570966798422301991069233423052047573723017573811854447144591388611545295336479676711135093748524215062079916506134402329979650885359052525127585725226235274380415403877926132099800327766309604816799309017969361197829094471646886280677088152723532310326801778432
e1 = 516257683822598401
e2 = 391427904712695553
e3 = 431785901506020973
n=1858284081017011776897142483530706248351014197676168270132930318711536519639284920939350511528325590655669305434894548271
E = EllipticCurve(IntegerModRing(n), [a, b])
E1=E(C1[0],C1[1])
E2=E(C2[0],C2[1])
E3=E(C3[0],C3[1])
l1,s1,m1=xgcd(e1,e2)
l2,s2,m2=xgcd(e2,e3)
l3,s3,m3=xgcd(e1,e3)
E1*s3+E3*m3
#(568187760467717269610985553206613709901686770919725280411069329483654912 : 902383579564357536192281359415338858998812047575951055596174651153047572493238086026951049981445179941533576636231499174 : 1)
long_to_bytes(568187760467717269610985553206613709901686770919725280411069329483654912 )
#b'RSA_0n_ECC_1s_mor3_Ineres7ing\x00'
贴几个主要函数吧
n0 = 30798082519452208630254982405300548841337042015746308462162479889627080155514391987610153873334549377764946092629701
g = 91289086035117540959154051117940771730039965839291520308840839624996039016929
class LCG():
def __init__(self) -> None:
self.n = next_prime(2**240)
self.a = getRandomNBitInteger(85)
self.seed = randint(1, self.n-1)
def next(self):
self.seed = (self.seed ** 3 * self.a + randint(-2**230, 2**230) + randint(1,100)) % self.n
return self.seed
def gift():
lcg = LCG()
outputs = []
for i in range(30):
outputs.append(int(lcg.next()))
return outputs, lcg.a
gift, a = gift()
def hash(msg):
key = bin(a)[2:]
n = n0
msg = list(map(ord,msg))
for i in range(len(msg)):
if key[i] == '1':
n = g * (2 * n + msg[i])
else:
continue
n = n & ((1 << 383) - 1)
return (n - 0xdeedbeef114514) % (1 << 100)
def proof_of_work(self):
rounds = 1000
pseudo_prime = int(self.recv(prompt=b'[+] Plz Tell Me your number: '))
if isPrime(pseudo_prime):
self.send(b"\nNo! it's a prime, go away!")
self.request.close()
for i in range(rounds):
if pow(randint(2, pseudo_prime), pseudo_prime - 1, pseudo_prime) != 1:
self.send(b"\nYou failed in round " + str(i + 1).encode() + b', bye~~')
self.request.close()
self.send(b"\nCongratulations, you have passed the proof_of_work!\n")
return True
def handle(self):
signal.alarm(300)
step1 = self.proof_of_work()
if not step1:
self.request.close()
self.send(banner)
self.send(b"\nNew challenge now! Please give me 2 diff strings whose hashes are the same~~")
self.send(b'Here is my gift for you: \n' + str(gift).encode())
string1 = self.recv().decode()
string2 = self.recv().decode()
if string1 == string2:
self.send(b"\nNo! They are the same one!")
self.request.close()
if hash(string1) == hash(string2):
self.send(b'\nGood job~ Here you are!')
self.send(flag)
self.send(b"\nConnection has been closed.")
self.request.close()
感觉这题非预期的太离谱吧,不用求a就能弄出来。
首先是proof_of_work函数,看见伪素数了吧,没见过不要紧,肯定出过CTF,直接谷歌搜它
具体看这里
然后伪素数就不说了,然后分析一下这个hash算法
首先msg不能超过key,然后仅仅对key[i]=1进行线性乘法取高位操作。其实通过这个点就能发现,只要我的string1,string2在key[i]=0时对应的字符串不一样就得到flag了。
其次还给了gift一串output列表,可以算出key。不过这里非预期,可以直接一个个试,不用求解key
举例
key=111100时。就算你不知道s1='10';s2='11',错了就s1='110';s2='111';一个个试就能出来
虽然key解出来了,但是修复版的还是不会做,等大佬的wp再看一看
不喜欢看这种线性生成器取高位的算法过程,也不知道咋做。
这里写一下造格子求key吧
2^230在2^240格上,又是经典的格求解,板子格,具体看看我之前的lattice
gift=[296573528337899862057373180194980708223274463728145168831135105115654778, 455186127980239474495608903697889181440710258959911027908147869237551777, 1276519476803268530539551384576747922680682249072593907646336824488737290, 318729441805449271247653400089293616463408660422109161477197551976329601, 1453192863448861889097819518420494682901210398546083168108144797139158616, 167401709171428378612788211013018031298925487777725176951591071540663434, 1618918110526609245418399732567046391465816098421830020766840673188047596, 22680620383315616539735295267351041211845370812074693249639279679258805, 652894084366158354115366241978667413491280582587801280248262111853228825, 1032683558363907155793489630878306211807958955841269934539321369910608779, 1162405325606833785827362193820095712687633788257346173171916173796097603, 769795968496951219143643124023899510172159311159325243279338444869202111, 1704945322949308508097171641785617776241729231561538687887677587170610741, 1750374376192197102544137895770148955485763465835183207207888725178114412, 704576259341301861771449232123342466784196393420984330325805772133277045, 52535098471065791171853633284891495515209981316421500065364557611191889, 357079925451015783949517215462853554895140034378894487733005693644584461, 760100785906712438723213869333688462493739360083157614937977379968172731, 1250581222075491710101261172153705953954300943576548551254551913647000446, 1296471333318006906454567780313271210559629157075433971131587849468565402, 144282519732275772103153272063583611512516973724637072139761912302806267, 988487551129271230513999329516266250649536505499643208910302166176096828, 1589740002819219990875207720870988576492705459106199897447452397081617948, 821760585081068791950916904936802649578346378801222118242850895710814408, 917649785756724152306645253518988254564092894769184933822507968003467972, 1613337869320896820132658952963387975482231466387851445850357998552621305, 724841407794849452241032285880585161261775264941463163994929522228918064, 464902613095787251066523101591605547310981246278321755670364163651534962, 684677155506057535061060874048792069041112708006699632787123970750059026, 1035686520917692423582549431741021335245388181439694374497888309082567915]
M=Matrix(ZZ,31,31)
for i in range(29):
M[i,i]=n
for i in range(29):
M[29,i]=gift[i]^3
M[30,i]=gift[1+i]
M[29,29]=2^145
M[30,30]=2^230
res=M.LLL()[0]
res
#(-422705657762824640739028797127916533011921368434693369873180670640537, 995859786462463242150720578132147089724688479477991806610005663036221, 1155879448698036021830805454330651570502153519638481863287268493524504, -241822270384441961133814307139107195547589473920049595599156837228563, 1370167402837437724685930037573171875628363471768867713707405330523218, -1016984537373726142817663323661005444372855071917515796263886148956163, -145411097990297543696105939094694815391851059175354158785742724570698, -144783970145085740907348148555338219848375640665701028023720607095156, -540265426524428551197659549505450964431930099557463892968863025665723, 157418456433551683553815112124000306999600319945165537507654737491526, -1326616897799404949965871791683349968538794453683526104136974817616466, -1585530188194242203334185143948493835811252079980754080777623587358378, -1047313374284533586876717820536431779346582224711519988445028433233003, -229897346703410999399263141166564772813967876598018607998514967825729, -248127669336106880472166151287186478607996849385692690413912795321556, 1525043764516030673075599255078984725124943002661536724097596821211495, -1714357227521945197913222690197224352576928641071289505771578563369509, 549046599411641822885838307304160240972287047110986827435708547515793, 994413500937873390786589334278502513549071069840174022492945976900142, -554828025012200686905279114432868629551116279956311789668354245573201, -1400427969626712158137274681604513412997422444127264623218607616548780, -908423371686630632154292798024285238613001672577358452246839205977441, 872204882161605559164368119973710414766206765738641620819546368887862, 257433575731686204504023471209556680416128790239117419443741633054322, -794736585954695803653934157096200454759777713693190685934668589565541, -103951021527892919621293984446273747018354314434790637449083702732766, 251129475297011860156165906057758930471561731456539619447043450434055, -674094100143399269401639160098320581058642525752192138264462694885165, -222673028634789545754535139952443049006226068386551057105485236594966, -960769702898856958558195273648482299274338241096357039797505001259008, 1725436586697640946858688965569256363112777243042596638790631055949824)
assert gcd(960769702898856958558195273648482299274338241096357039797505001259008,2^145)==2^145
960769702898856958558195273648482299274338241096357039797505001259008//2^145
#21541201747871664065778869
看了wp,复现一下。
def hash(msg,key):
n = n0
msg = list(map(ord,msg))
for i in range(len(msg)):
if key[i] == '1':
n = g * (2 * n + msg[i])
else:
continue
n = n & ((1 << 383) - 1)
return (n - 0xdeedbeef114514) % (1 << 100)
真没想到&((1 << 383) - 1)就是%2^383,不然也是能做出来的
还有,最后对2^100取模,这样看来其实连模2^383也可以省去,在2^100下线性运算而已
官方wp给的是在2^383下进行的,我复现一下在2^383下数据还是太大了,是不行的
可以具体把这个线性同余式子展开看一下
举一个四次之后的例子看一看,这个线性数列的通项公式
其中c为key中的1的个数
这不就跟格的基一样吗,找到两个mi相近的
K就是可以算出来的固定值,只需要m,n对应位数满足这个即可,进一步化简
m-n差距不能过大,因为是可见字符
构造m-n在格上
注意顺序,mi-ni对应的是(2g)^(c-i)
exp
n0 = 30798082519452208630254982405300548841337042015746308462162479889627080155514391987610153873334549377764946092629701
g = 91289086035117540959154051117940771730039965839291520308840839624996039016929
a=21541201747871664065778869
def hash(msg):
key = bin(a)[2:]
n = n0
msg = list(map(ord,msg))
for i in range(len(msg)):
if key[i] == '1':
n = g * (2 * n + msg[i])
else:
continue
n = n & ((1 << 383) - 1)
return (n - 0xdeedbeef114514) % 2^100
key=bin(a)[2:]
c=key.count('1')
M=Matrix(ZZ,c+1,c+1)
for i in range(c):
M[i,i]=1
M[i,c]=(2*g)^(c-1-i) %(2^100)
M[c,c]=2^100
res=M.LLL()
#res[0]
#(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1)
#res[1]
#(1, 0, -2, 1, 0, -2, 0, -1, 0, 0, 0, 0, 2, -2, 2, 6, -1, 2, 3, -2, -1, 0, 1, 0, -1, 2, 0, -1, -2, -1, 0, -3, 0, 4, -1, 1, 2, 0, 0, 0, 0, 0, 0)
m = ''
time = 0
for i in range(len(key)):
if key[i] == '1':
m += chr(97+res[1][time])
time+=1
else:
m += chr(97)
hash(m),hash('a'*len(m)),m,b'a'*len(m)
有没有师傅带我一起玩,私信即可收留(手动哭泣)