NewStarCTF week2 Rabin题解
from Crypto.Util.number import * from somewhere_you_do_not_know import flag #flag格式为 flag{XXXX} def ezprime(n): p=getPrime(n) while p%4!=3: p=getPrime(n) return p p=ezprime(512) q=ezprime(512) n=p*q m=bytes_to_long(flag) m=(m<<(300))+getRandomNBitInteger(300) assert m**2>n and m<n c=pow(m,4,n) print('c=',c) print('p=',p) print('q=',q) ''' c= 59087040011818617875466940950576089096932769518087477304162753047334728508009365510335057824251636964132317478310267427589970177277870220660958570994888152191522928881774614096675980017700457666192609573774572571582962861504174396725705862549311100229145101667835438230371282904888448863223898642183925834109 p= 10522889477508921233145726452630168129218487981917965097647277937267556441871668611904567713868254050044587941828674788953975031679913879970887998582514571 q= 11287822338267163056031463255265099337492571870189068887689824393221951058498526362126606231275830844407608185240702408947800715624427717739233431252556379 就要花里胡哨( '''
观察题目,可以发现与rsa不同的是e是偶数,也就是变异rsa,rabin解密。
c =pow(m,4,n)可以得出m^4 =c mod n 因此本题的思路是开方
利用二次剩余先开二次方得到m^2的解
c1=pow(c,(p+1)//4,p) c2=pow(c,(q+1)//4,q) cp1=p-c1 cp2=q-c2 t1=gmpy2.invert(p,q)#p的模q逆元 t2=gmpy2.invert(q,p)#q的模p逆元 m1=(q*c1*t2+p*c2*t1)%n m2=(q*c1*t2+p*cp2*t1)%n # or m2=n-m1 m3=(q*cp1*t2+p*c2*t1)%n m4=(q*cp1*t2+p*cp2*t1)%n # or m4=n-m3
通过 assert m**2>n and m<n 可以发现我们无法对m^2直接进行开方
因此还是通过二次剩余来求解m
这边注意,因为会出现16种解,所以我们最好不要求解所有解,可以一组一组慢慢来,得出结果后观察题目,需要移位,因此结果移位再转字符,出现flag
x1=q*c1*t2+p*c2*t1 x2=q*c1*t2+p*cp2*t1 x3=q*cp1*t2+p*c2*t1 x4=q*cp1*t2+p*cp2*t1 mm1 = pow(x1,(p+1)//4,p) mm11 = pow(x1,(q+1)//4,q) mm2 = pow(x2,(p+1)//4,p) mm22 = pow(x2,(q+1)//4,q) mm3 = pow(x3,(p+1)//4,p) mm33 = pow(x3,(q+1)//4,q) mm4 = pow(x4,(p+1)//4,p) mm44 = pow(x4,(q+1)//4,q) l1 = (q*mm1*t2 + p*mm11*t1)%n l11 = (q*mm1*t2 + p*(q-mm11)*t1)%n l111= (q*(p-mm1)*t2 + p*mm11*t1)%n l1111 = (q*(p-mm1)*t2 + p*(q-mm11)*t1)%n for i in(l1,l11,l111,l1111): i = (i>>300) x = long_to_bytes(i) print(x)
最后得出flag
下面给出完整代码
from Crypto.Util.number import * import gmpy2 c= 59087040011818617875466940950576089096932769518087477304162753047334728508009365510335057824251636964132317478310267427589970177277870220660958570994888152191522928881774614096675980017700457666192609573774572571582962861504174396725705862549311100229145101667835438230371282904888448863223898642183925834109 p= 10522889477508921233145726452630168129218487981917965097647277937267556441871668611904567713868254050044587941828674788953975031679913879970887998582514571 q= 11287822338267163056031463255265099337492571870189068887689824393221951058498526362126606231275830844407608185240702408947800715624427717739233431252556379 n = p*q e = 4 c1=pow(c,(p+1)//4,p) c2=pow(c,(q+1)//4,q) cp1=p-c1 cp2=q-c2 t1=gmpy2.invert(p,q)#p的模q逆元 t2=gmpy2.invert(q,p)#q的模p逆元 m1=(q*c1*t2+p*c2*t1)%n m2=(q*c1*t2+p*cp2*t1)%n # or m2=n-m1 m3=(q*cp1*t2+p*c2*t1)%n m4=(q*cp1*t2+p*cp2*t1)%n # or m4=n-m3 x1=q*c1*t2+p*c2*t1 x2=q*c1*t2+p*cp2*t1 x3=q*cp1*t2+p*c2*t1 x4=q*cp1*t2+p*cp2*t1 mm1 = pow(x1,(p+1)//4,p) mm11 = pow(x1,(q+1)//4,q) mm2 = pow(x2,(p+1)//4,p) mm22 = pow(x2,(q+1)//4,q) mm3 = pow(x3,(p+1)//4,p) mm33 = pow(x3,(q+1)//4,q) mm4 = pow(x4,(p+1)//4,p) mm44 = pow(x4,(q+1)//4,q) l1 = (q*mm1*t2 + p*mm11*t1)%n l11 = (q*mm1*t2 + p*(q-mm11)*t1)%n l111= (q*(p-mm1)*t2 + p*mm11*t1)%n l1111 = (q*(p-mm1)*t2 + p*(q-mm11)*t1)%n for i in(l1,l11,l111,l1111): i = (i>>300) x = long_to_bytes(i) print(x)