Bigrsa
from Crypto.Util.number import * from flag import * n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061 n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073 e = 65537 m = bytes_to_long(flag) c = pow(m, e, n1) c = pow(c, e, n2) print("c = %d" % c) # output # c = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264
It is a sign in question. First encrypt the flag with the public key (e,n1), and then encrypt it with the public key (e,n2) for the second time.
So we just need to decrypt it in turn.
There is a common factor between n1 and n2, and pq can be decomposed by calculation.
Exp:
import libnum, gmpy2 n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061 n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073 e = 65537 c = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264 p = gmpy2.gcd(n1,n2) q1 = n1//p q2 = n2//p phi1 = (p-1)*(q1-1) phi2 = (p-1)*(q2-1) d1 = gmpy2.invert(e,phi1) d2 = gmpy2.invert(e,phi2) m = pow(pow(c,d2,n2),d1,n1) flag = libnum.n2s(m) print(flag)
Ring Ring Ring
This question only gives IP and port to interact with the server. There is no environment to reproduce now.
General process:
- hash verification first
- Enter 100 groups (a,b,c,d,e) so that a**4+b**4+c**4+d**4==e**2
He has only one equation here, and there are no other conditions that restrict abcde, so we can assume a==b==c==d
Then calculate e=2*a**2.
However, I cannot use Alibaba cloud because I need to connect to the server through VPN. As a result, I need to install python pwntools locally to interact with the server. But the virtual machine suddenly doesn't work, so it's just manual.
From 1 to 100. sbcd inputs are the same, and e takes twice their square.
After 100 times, I got the flag.
RSA?
This problem is a sage file, which gives the encryption logic. I don't say much and analyze it directly.
import os from Crypto.Util.number import * flag = "GWHT{xxxxxxxxx}" p = getPrime(256) q = getPrime(256) n = p*q N = (p-1)*(q-1) e = 65537 Mx = bytes_to_long(os.urandom(30)) My = bytes_to_long(flag) Z1 = (Mx*My)%n inv_Z1 = inverse_mod(Z1, n) inv_2 = inverse_mod(2, n) X = ((Z1+inv_Z1)*inv_2)%n Y = My inv_Y = inverse_mod(Y, n) a = ((inv_Z1-X)*inv_Y)%n D = (a*a)%n xy = lambda (x1,y1),(x2,y2) : ((x1*x2+D*y1*y2)%n, (x1*y2+x2*y1)%n) def getloop((x,y), e): ret = (x, y) for i in range(e-1): ret = xy(ret, (x,y)) return ret print n print getloop((X, Y), e) print a # 13390709926509813526471364597371124446888078365567927211781799241724742352679484983709219580483800891886832613684875066109177882219522305348565532970795023 # (5404548088049249951619519701935576492239293254135836357417714329205323074367876875480850741613547220698045360461761929952847796420174204143917852624050110, 2110372753170830610718226848526649992911771424441223687775304654852191999130502986109306355582366065947895295520226816523397652918227241733632791793362785) # 1762039418842677123086894939949574689744108610561557889235294034870342076452734215004689409493802437034960516295735815195656138656970901855976802991519141
The above is the normal RSA construction process. Starting from line 10, it is the focus of attention.
Mx = bytes_to_long(os.urandom(30)) My = bytes_to_long(flag) Z1 = (Mx*My)%n inv_Z1 = inverse_mod(Z1, n) inv_2 = inverse_mod(2, n)
A random number (Mx) and flag (My) are generated here.
Z1 is Mx multiplied by My
We can find that all operations will take the modulus of n as long as they exceed n, so we can use mathematical formulas to express these parameters as long as we set it within the range of n.
X = ((Z1+inv_Z1)*inv_2)%n Y = My inv_Y = inverse_mod(Y, n)
a = ((inv_Z1-X)*inv_Y)%n D = (a*a)%n
xy = lambda (x1,y1),(x2,y2) : ((x1*x2+D*y1*y2)%n, (x1*y2+x2*y1)%n) def getloop((x,y), e): ret = (x, y) for i in range(e-1): ret = xy(ret, (x,y)) return ret
Here is the key code, which defines a function and throws a binary after 65536 loop calculations.
It's a bit confusing to see such a complex operation at the beginning, but in fact, you'll find the law as long as you calculate it two or three times.
I can see some rules when I calculate here.
Can be calculated here, the answer is very close.
Because the conditions in the code are basically pushed by us, we only need to combine the known information with the formula we deduced, and the problem should be over.
We can find that the result derived from the above formula is very close to Xn, so we can substitute Xn to get:
However, Yn, Xn and a have been informed to us, so we can find the result of Mxn+1Myn+1.
But at this step, we can find that the result we obtained is only (Mx*My) 65537. Isn't this m=pow(c,d,n) in RSA?
I expect that there will be a hint about decomposing n or get the answer directly at this step, but this step only gives us ciphertext, so we need to find another way to decompose n.
However, there are no more tips on decomposing n in the code. Note that the generated p and q are 256 bits, which are relatively small, so they may be exploded. So we use yafu to decompose n, and the result is second.
When you decompose pq, it's easy to find Mx*My.
But flag is actually My. We also need to extract My from Mx*My.
Go back to the formula of a again.
We can find that Mx and My of this formula are not homogeneous. Therefore, a My can be extracted by moving items.
Finally, you can get the value of My and get the flag.
Exp:
import libnum, gmpy2 n = 13390709926509813526471364597371124446888078365567927211781799241724742352679484983709219580483800891886832613684875066109177882219522305348565532970795023 p = 115718235064789220654263009993128325569382592506655305434488398268608329541037 q = n//p e = 65537 Xn, Yn = 5404548088049249951619519701935576492239293254135836357417714329205323074367876875480850741613547220698045360461761929952847796420174204143917852624050110, 2110372753170830610718226848526649992911771424441223687775304654852191999130502986109306355582366065947895295520226816523397652918227241733632791793362785 a = 1762039418842677123086894939949574689744108610561557889235294034870342076452734215004689409493802437034960516295735815195656138656970901855976802991519141 c = (Xn - Yn * a)%n d = gmpy2.invert(e,(p-1)*(q-1)) xy = pow(c,d,n) flag = ((1-xy*xy)*gmpy2.invert(2,n)*gmpy2.invert(xy,n)*gmpy2.invert(a,n))%n print(libnum.n2s(flag))