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 = e = 65537 enc = beta = tip = (n-1)//(2*beta) for i in range(10000): #获取x + y的值 x_add_y = tip % beta + beta*i #根据x + y 获取 x * y x_mul_y = (tip - x_add_y)//(2*beta) try: if iroot(x_add_y**2 - 4*x_mul_y,2)[1]: #解方程获取x 和 y y = (x_add_y - iroot(x_add_y**2 - 4*x_mul_y,2)[0] )//2 x = x_add_y - y p = 2*y*beta + 1 q = 2*x*beta + 1 phi = (p-1)*(q-1) d = inverse(e,int(phi)) print long_to_bytes(pow(enc,d,n)) except: pass
# 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
defint2str(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))])
defget_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
defsign(m): y, h, b = get_parameter(m) r = getStrongPrime(512) s = (y * powmod(h, r, p)) % p
return str(r),str(s)
defverify(m, r, s): y, h, b = get_parameter(m) if s == ((y * powmod(h, r, p)) % p): returnTrue else: returnFalse
# Give me the (r2,s2) if r2 != r1 and s2 == s1 and verify(m2, r2, s2): print("Congratulation!Here is your flag: %s" % flag)
这道题的他会提供两个msg,然后你需要给他们签名,要求是,签名中两者的s相等,但是r不相等
我们提取一下信息,
签名的验证是 s == ((y * powmod(h, r, p)) % p)
其中 x 就是要被签名的信息, y = powmod(g, x, p), h = powmod(g, b, p) , b = powmod(a, a, p - 1) ,
a = bytes_to_long(hashlib.sha256(long_to_bytes(y).rjust(128, “\0”)).digest()) ,显得挺麻烦,但是由于我们是知道参数x, g, p的,因此y是一个已知的常数,从而a也可以看成一个已知常数即可,继而b、h也会是一个已知常数。(全都已知,完全不用管了)
from pwn import * from Crypto.Util.number import * sh=remote("139.129.98.9","30001") from pwnlib.util.iters import mbruteforce from hashlib import sha256 import hashlib from math import gcd context.log_level = 'debug' defproof_of_work(sh): sh.recvuntil("XXXX+") suffix = sh.recvuntil(')').decode("utf8")[:-1] log.success(suffix) sh.recvuntil("== ") cipher = sh.recvline().strip().decode("utf8") proof = mbruteforce(lambda x: sha256((x + suffix).encode()).hexdigest() == cipher, string.ascii_letters + string.digits, length=4, method='fixed') sh.sendlineafter("Give me XXXX:", proof)
proof_of_work(sh) sh.interactive()
# These three are constants p = 12039102490128509125925019010000012423515617235219127649182470182570195018265927223 g = 10729072579307052184848302322451332192456229619044181105063011741516558110216720725
defint2str(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))])
defget_parameter(m): x = int2str(m, 'little') y = pow(g, x, p) a = bytes_to_long(hashlib.sha256(long_to_bytes(y).rjust(128, b"\0")).digest()) b = pow(a, a, p - 1) h = pow(g, b, p)
return y, h, b
defsign(m): y, h, b = get_parameter(m) r = getStrongPrime(512) s = (y * powmod(h, r, p)) % p
return str(r),str(s)
defverify(m, r, s): y, h, b = get_parameter(m) if s == ((y * powmod(h, r, p)) % p): returnTrue else: returnFalse
sh.recvuntil("Here is the frist message(64 bytes):") message1 = bytes.fromhex(sh.recvuntil("\n")[:-1].decode()).decode() sh.recvuntil("Here is the second message(64 bytes):") message2 = sh.recvuntil("\n")[:-1].decode() print("message2",message2) message2 = bytes.fromhex(message2).decode()
sh.sendline("3") sh.recvuntil("Please give me the (r,s) of the second message:") print("("+str(r2)+","+str(message2_s)+")") sh.sendline("("+str(r2)+","+str(message2_s)+")") sh.interactive()
[DEBUG] Received 0xd bytes: b'Give me XXXX:' [DEBUG] Sent 0x5 bytes: b'bwUI\n' [DEBUG] Received 0x4f bytes: b'Hello,guys!Welcome to my ECC Signature System!I promise no one can exploit it!\n' [DEBUG] Received 0x269 bytes: b'Howevers if you can exploit it in 10 times,I will give what you want!\n' b'Here is the frist message(64 bytes):fipoN9jy/*@~J:] PcZY8{&X!7v+\\duTln_#k(WK^Q2L)<SbM$-V=Ex3Uw|h,%}F\n' b'Here is the second message(64 bytes):%wh-(xJ4kR+7<^Zv9,Ol\\Kp/&"FHbc_ D@Y*mSos}V?.#L{!3B8QiP=nqCI[y:X2\n' b'Try to calculate the same signature for this two messages~\n' b'(((Notice: curve = SECP256k1, hashfunc = sha1)))\n' b'\n' b'ECC Signature System:\n' b' 1. Show your pubkey\n' b' 2. Generate new prikey\n' b' 3. Update your pubkey\n' b' 4. Sign a message\n' b' 5. Verify a message\n' b' 6. Exploit\n' b' 7. Exit\n' b'\n' b'You have only 10 times to operate!\n' b'Please choice your options:'
from pwn import * from Crypto.Util.number import * sh=remote("139.129.98.9","30002") from pwnlib.util.iters import mbruteforce from hashlib import sha256 import hashlib from math import gcd context.log_level = 'debug'
sh.recvuntil("Here is the frist message(64 bytes):") msg1 = sh.recvuntil("\n")[:-1]
sh.recvuntil("Here is the second message(64 bytes):") msg2 = sh.recvuntil("\n")[:-1] message = hex(bytes_to_long(msg1))[2:] e1=bytes_to_long(sha1(msg1)) e2=bytes_to_long(sha1(msg2))
sh.recvuntil("Please choice your options:") sh.sendline("3") sh.recvuntil("Please give me your public_key(hex):") sh.sendline(newpubkey)
sh.recvuntil("Please choice your options:") sh.sendline("6") sh.recvuntil("Please give me the signature(hex) of the frist message:\n") sh.sendline(newsignature) sh.recvuntil("Please give me the signature(hex) of the second message:\n") sh.sendline(newsignature)