# These three are constants
p = 12039102490128509125925019010000012423515617235219127649182470182570195018265927223
g = 10729072579307052184848302322451332192456229619044181105063011741516558110216720725
# random generation
m1 = "test1"
m2 = "test2"
# Initialization
r1, s1 = sign(m1)
# r1 will be provided to player
def int2str(data, mode="big"):
if mode == "little":
return sum([ord(data[_]) * 2 ** (8 * _) for _ in range(len(data))])
elif mode == "big":
return sum([ord(data[::-1][_]) * 2 ** (8 * _) for _ in range(len(data))])
def get_parameter(m):
x = int2str(m, 'little')
y = powmod(g, x, p)
a = bytes_to_long(hashlib.sha256(long_to_bytes(y).rjust(128, "\0")).digest())
b = powmod(a, a, p - 1)
h = powmod(g, b, p)
return y, h, b
def sign(m):
y, h, b = get_parameter(m)
r = getStrongPrime(512)
s = (y * powmod(h, r, p)) % p
return str(r),str(s)
def verify(m, r, s):
y, h, b = get_parameter(m)
if s == ((y * powmod(h, r, p)) % p):
return True
else:
return False
# Give me the (r2,s2)
if r2 != r1 and s2 == s1 and verify(m2, r2, s2):
print("Congratulation!Here is your flag: %s" % flag)
考虑到 s = g m + b r s = g^{m+br} s=gm+br, 要有 s 1 = = s 2 s1 == s2 s1==s2,就是 m 1 + b 1 r 1 = m 2 + b 2 r 2 m o d p h i ( p ) m_1 + b_1 r_1 = m_2 + b_2 r_2 \mod phi(p) m1+b1r1=m2+b2r2modphi(p),看了翅膀师傅wp知道这里更准确应该用 m 1 + b 1 r 1 = m 2 + b 2 r 2 m o d q m_1 + b_1 r_1 = m_2 + b_2 r_2 \mod q m1+b1r1=m2+b2r2modq求出r2(其中q是g模p的阶,可用sage求出)。
from pwn import *
from parse import *
from pwnlib.util.iters import bruteforce
import string
from hashlib import sha256
from Crypto.Util.number import *
import hashlib
from gmpy2 import gcd,invert
def brute_force(prefix,s):
return bruteforce(lambda x:sha256(x+prefix).hexdigest()==s,string.ascii_letters+string.digits,length=4,method='fixed')
p = 12039102490128509125925019010000012423515617235219127649182470182570195018265927223
g = 10729072579307052184848302322451332192456229619044181105063011741516558110216720725
def int2str(data, mode="big"):
if mode == "little":
return sum([ord(data[_]) * 2 ** (8 * _) for _ in range(len(data))])
elif mode == "big":
return sum([ord(data[::-1][_]) * 2 ** (8 * _) for _ in range(len(data))])
def get_parameter(m):
x = int2str(m, 'little')
y = pow(g, x, p)
a = bytes_to_long(hashlib.sha256(long_to_bytes(y).rjust(128, "\0")).digest())
b = pow(a, a, p - 1)
h = pow(g, b, p)
return x, y, h, b
def sign(m, r):
x, y, h, b = get_parameter(m)
s = (y * pow(h, r, p)) % p
return s
def verify(m, r, s):
x, y, h, b = get_parameter(m)
if s == ((y * pow(h, r, p)) % p):
return True
else:
return False
r=remote('139.129.98.9',30001)
data = r.recvline()
prefix, s = parse("sha256(XXXX+{}) == {}",data)
r.recvuntil('Give me XXXX:')
r.sendline(brute_force(prefix,s))
r.recvline()
r.recvline()
m1 = long_to_bytes(int(parse("Here is the frist message(64 bytes):{}",r.recvline())[0],16))
m2 = long_to_bytes(int(parse("Here is the second message(64 bytes):{}",r.recvline())[0],16))
r1 = int(parse("The frist message's 'r':{}",r.recvline())[0])
print(m1)
print(m2)
M1,y1,h1,b1 = get_parameter(m1)
M2,y2,h2,b2 = get_parameter(m2)
s1 = sign(m1, r1)
q = p - 1
p1 = b1*r1
p2 = M2-M1
p3 = p1-p2
p4 = invert(b2,q)
r2 = (p3*p4)%q
s2 = sign(m2,r2)
r.recvuntil('Please choice your options:')
r.sendline('3')
r.sendlineafter('Please give me the (r,s) of the second message:',str((str(r2),str(s2))))
print(r.recvall())
from Crypto.Util.number import *
from gmpy2 import *
from secret import *
assert(flag.startwith('flag{')) and (flag.endwith('}'))
assert(is_prime(beta) and len(bin(beta)[2:]) == 512)
assert(len(bin(x)[2:]) == len(bin(y)[2:]))
# This is tip!!!
assert(tip == 2*x*y*beta + x + y)
p = 2*x*beta + 1
q = 2*y*beta + 1
assert(is_prime(p) and is_prime(q))
n = p*q
e = 65537
m = bytes_to_long(flag)
enc = powmod(m,e,n)
#n=17986052241518124152579698727005505088573670763293762110375836247355612011054569717338676781772224186355540833136105641118789391002684013237464006860953174190278718294774874590936823847040556879723368745745863499521381501281961534965719063185861101706333863256855553691578381034302217163536137697146370869852180388385732050177505306982196493799420954022912860262710497234529008765582379823928557307038782793649826879316617865012433973899266322533955187594070215597700782682186705964842947435512183808651329554499897644733096933800570431036589775974437965028894251544530715336418443795864241340792616415926241778326529055663
#e=65537
#enc=10760807485718247466823893305767047250503197383143218026814141719093776781403513881079114556890534223832352132446445237573389249010880862460738448945011264928270648357652595432015646424427464523486856294998582949173459779764873664665361437483861277508734208729366952221351049574873831620714889674755106545281174797387906705765430764314845841490492038801926675266705606453163826755694482549401843247482172026764635778484644547733877083368527255145572732954216461334217963127783632702980064435718785556011795841651015143521512315148320334442235923393757396733821710592667519724592789856065414299022191871582955584644441117223
#beta=11864389277042761216996641604675717452843530574016671576684180662096506094587545173005905433938758559675517932481818900399893444422743930613073261450555599
分析一下tip可求, t i p m o d b e t a = x + y m o d b e t a tip \mod beta = x + y \mod beta tipmodbeta=x+ymodbeta, p h i = ( t i p − x − y ) ∗ 2 ∗ b e t a phi = (tip - x - y)*2*beta phi=(tip−x−y)∗2∗beta。于是爆破 x + y x + y x+y即可。
import gmpy2
from Crypto.Util.number import *
n=17986052241518124152579698727005505088573670763293762110375836247355612011054569717338676781772224186355540833136105641118789391002684013237464006860953174190278718294774874590936823847040556879723368745745863499521381501281961534965719063185861101706333863256855553691578381034302217163536137697146370869852180388385732050177505306982196493799420954022912860262710497234529008765582379823928557307038782793649826879316617865012433973899266322533955187594070215597700782682186705964842947435512183808651329554499897644733096933800570431036589775974437965028894251544530715336418443795864241340792616415926241778326529055663
e=65537
enc=10760807485718247466823893305767047250503197383143218026814141719093776781403513881079114556890534223832352132446445237573389249010880862460738448945011264928270648357652595432015646424427464523486856294998582949173459779764873664665361437483861277508734208729366952221351049574873831620714889674755106545281174797387906705765430764314845841490492038801926675266705606453163826755694482549401843247482172026764635778484644547733877083368527255145572732954216461334217963127783632702980064435718785556011795841651015143521512315148320334442235923393757396733821710592667519724592789856065414299022191871582955584644441117223
beta=11864389277042761216996641604675717452843530574016671576684180662096506094587545173005905433938758559675517932481818900399893444422743930613073261450555599
tip = (n-1) // beta // 2
x_y = tip % beta
while 1:
x_y = x_y + beta
phi = (tip - x_y)*2*beta
d = gmpy2.invert(e, phi)
m = long_to_bytes(gmpy2.powmod(enc, d, n))
if m[0] == 102 and m[1] == 108:
print(m)
赛后翅膀师傅提示参考ASIS2020 RSASR,等于是前后一起爆破p和Reverse§。
#Author: Lazzzaro
#python2
n = 158985980192501034004997692253209315116841431063210516613522548452327355222295231366801286879768949611058043390843949610463241574886852164907094966008463721486557469253652940169060186477803255769516068561042756903927308078335838348784208212701919950712557406983012026654876481867000537670622886437968839524889
def t(a, b, k):
# sqrt(n)有512位2进制位, 需计算高低位每边的256位
if k == 256:
if a*b == n:
print(a, b)
return
for i in range(2):
for j in range(2):
# 对两个素数因子尝试爆破未遍历的位爆破
a1 = a + i*(2**k) + j*(2**(511-k))
b1 = b + j*(2**k) + i*(2**(511-k))
if a1*b1 > n:
# 当a1和b1过大
continue
if (a1+(2**(511-k)))*(b1+(2**(511-k))) < n:
# 当a1和b1过小
continue
if ((a1*b1)%(2**(k+1))) != (n%(2**(k+1))):
# 当a1*b1的最后k+1位(不变)与n的最后k+1位不同
continue
# 满足条件的(a1,b1)值,尝试继续遍历
t(a1, b1, k+1)
# 两个素数因子有512位2进制位, 尝试可能的所有中间位
for i in range(2):
t(i*(2**256), i*(2**256), 0)