March 16, 2014

RuCTF: Crypto 500 (decrypt message)

We have two hex crypted messages:
c1=61be5676e0f8311dce5d991e841d180c95b9fc15576f2ada0bc619cfb991cddfc51c4dcc5ecd150d7176c835449b5ad085abec38898be02d2749485b68378a8742544ebb8d6dc45b58fb9bac4950426e3383fa31a933718447decc5545a7105dcdd381e82db6acb72f4e335e244242a8e0fbbb940edde3b9e1c329880803931c
c2=9d3c9fad495938176c7c4546e9ec0d4277344ac118dc21ba4205a3451e1a7e36ad3f8c2a566b940275cb630c66d95b1f97614c3b55af8609495fc7b2d732fb58a0efdf0756dc917d5eeefc7ca5b4806158ab87f4f447139d1daf4845e18c8c7120392817314fec0f0c1f248eb31af153107bd9823797153e35cb7044b99f26b0
a public key and a helpful information about messages format, it is <message><signature>, where signature is "Alex" or "Jane".
So, since these messages are almost the same, seems like a stereotyped messages attack can be applied. Here is some documentation for this attack: http://www.cs.unc.edu/~reiter/papers/1996/Eurocrypt.pdf
So, first of all, we should get all public infomation from public key (that can be easily done with openssl), here is it:
N=114725527397185618184017233206819193913174443780510744606142335459665478168081417742295326326458510125306461590118257162988125409459000413629137879229803717947627133370343339582895822944017711093729671794212087753322731071609302218014807365556283824229308384059742494244873283137838666434755861643308137132991
e=12289
Now, we should find a delta between messages, delta=s2int("Jane")-s2int("Alex"), where s2int is an integer representation of these strings, s2int(x)=int(x.encode("hex"),16)
delta=150276333
We can write an equation:
x^e-c1=0 (mod N)
(x+delta)^e-c2=0 (mod N)
Now we can find one root using gcd (mod N) on these equations (it will look like x-d1, where d1 is a decrypted c1).
I've used Maple for that (I have an access to it at BINP), but most probably any proper CAS can be used. Maple input is:
Gcd(x^12289-68637824697847347325152429166246333419764472268780072757587048866758063980081812577868025346342305730846265857419258574014532773110290579119479245309675963105465063836966456434907272251685983171777876162066266988897465659231400350880563676874458715068009792182974259253289354555355553939832364038254785434396,(x+150276333)^12289-110415443960273889959772782974579149193774314415704667862564866051898265132264857882875118745675253074657904850129821237002854297780011314654171228045016426147668965474969735759528466512727814724894364646814997520314090351722043560006805335328354216183496479524826149827718661697262926144256033255227626825392) mod 114725527397185618184017233206819193913174443780510744606142335459665478168081417742295326326458510125306461590118257162988125409459000413629137879229803717947627133370343339582895822944017711093729671794212087753322731071609302218014807365556283824229308384059742494244873283137838666434755861643308137132991
And the output is:
x+114725527397185618184017233206819193913174443780510744606142335459665478168081417742295326326458510125306461590118257162988125409459000413629137879229803717947627133370343339582895822944017711093729671019855461413586767003863579981160973816022105611176850339001207780559316286358645404676493453728647627853383
So d1=-114725527397185618184017233206819193913174443780510744606142335459665478168081417742295326326458510125306461590118257162988125409459000413629137879229803717947627133370343339582895822944017711093729671019855461413586767003863579981160973816022105611176850339001207780559316286358645404676493453728647627853383
But d1 is positive, so real decrypted d1 is N+d1 mod N, so d1=774356626339735964067745722236853833549534178213052458045058534713685556996779193261758262407914660509279608
Now use print hex(d1)[2:-1].decode("hex") to get the flag:
The key is RUCTF_StandBackImGonnaDoMath. Alex

No comments:

Post a Comment