defmain(): signal.alarm(60) ifnot proof_of_work(): return secret = getrandbits(1024) print("Listen...The secret iz...M2@9c0f*#aF()I!($Ud3;J..." "Hello?...really noisy here again...God bless you get it...") for i in range(64): try: op = input().strip() num = input().strip() except EOFError: return ifnot str.isnumeric(num): print("INVALID NUMBER") continue num = int(num) if op == 'god': print(num * getrandbits(992) % secret) elif op == 'bless': if num == secret:
try: from datetime import datetime from flag import FLAG except Exception as e: FLAG = "but something is error. Please contact the admin."
from pwn import * from hashlib import sha256 from tqdm import tqdm from Crypto.Util.number import *
def GCRT(mi, ai): assert (isinstance(mi, list) and isinstance(ai, list)) curm, cura = mi[0], ai[0] for (m, a) in zip(mi[1:], ai[1:]): d = int(GCD(curm, m)) c = a - cura assert (c % d == 0) K = c // d * inverse(curm // d, m // d) cura += curm * K curm = curm * m // d cura %= curm return cura % curm, curm
def proof_of_work(sh): sh.recvuntil("SHA256(\"") nonce = sh.recv(8) sh.recvuntil('with \"00000\"') fora in tqdm(range(0x30, 0x7f)): forb in range(0x30, 0x7f): forc in range(0x30, 0x7f): for d in range(0x30, 0x7f): rest = chr(a) + chr(b) + chr(c) + chr(d) m = (nonce.decode('latin1') + rest).encode("Latin-1") ifsha256(m).digest().hex().startswith("00000"): sh.sendline(rest) sh.recvuntil('again...God bless you get it...') return
k1 = int(k1_str, 16) d1 = self.sks、 s = (d1 * k1 * s2 + d1 * s3 - r) % self.n if s == 0or s == (self.n - r): return None return'%064x%064x' % (r, s)
defverify(self, Sign, data): r = int(Sign[0:self.para_len], 16) s = int(Sign[self.para_len:2 * self.para_len], 16) e = int(data.hex(), 16) t = (r + s) % self.n if t == 0: return0
x = int(P1[0:self.para_len], 16) return r == ((e + x) % self.n)
def_kg(self, k, Point): if (k % self.n) == 0: return'0' * 128 Point = '%s%s' % (Point, '1') mask_str = '8' for i in range(self.para_len - 1): mask_str += '0' mask = int(mask_str, 16) Temp = Point flag = False for n in range(self.para_len * 4): ifflag: Temp = self._double_point(Temp) if (k & mask) != 0: ifflag: Temp = self._add_point(Temp, Point) else: flag = True Temp = Point k = k << 1 returnself._convert_jacb_to_nor(Temp)
def_double_point(self, Point): l = len(Point) len_2 = 2 * self.para_len if l < self.para_len * 2: return None else: x1 = int(Point[0:self.para_len], 16) y1 = int(Point[self.para_len:len_2], 16) if l == len_2: z1 = 1 else: z1 = int(Point[len_2:], 16)
form = '%%0%dx' % self.para_len form = form * 3 return form % (X3, Y3, Z3)
def_convert_jacb_to_nor(self, Point): len_2 = 2 * self.para_len x = int(Point[0:self.para_len], 16) y = int(Point[self.para_len:len_2], 16) z = int(Point[len_2:], 16) z_inv = pow(z, int(self.ecc_table['p'], base=16) - 2, int(self.ecc_table['p'], base=16)) z_invSquar = (z_inv * z_inv) % int(self.ecc_table['p'], base=16) z_invQube = (z_invSquar * z_inv) % int(self.ecc_table['p'], base=16) x_new = (x * z_invSquar) % int(self.ecc_table['p'], base=16) y_new = (y * z_invQube) % int(self.ecc_table['p'], base=16) z_new = (z * z_inv) % int(self.ecc_table['p'], base=16) if z_new == 1: form = '%%0%dx' % self.para_len form = form * 2 return form % (x_new, y_new) else: return None
if __name__ == '__main__': sk = func.random_hex(len(sm2p256v1_ecc_table['n'])) tsm2 = TSM2(sk) print('pk:%s' %tsm2.pk) print('pks:%064x'%tsm2.pks) for i in range(10): op = input('op: ').strip() if op == 'sign': sign(tsm2) elif op == 'verify': verify(tsm2) else: print("""sign: sign message verify: verify message""")
这个验证函数有三个输入:r,s,e,然后这里有一个self._kg ,这个其实就是一个椭圆曲线上的一个乘法,所以P1 = s * g,g是椭圆曲线上的一个基点,P2 = t * pk ,代码前头有对pk的定义 self.pk = self._kg(self.sk, ecc_table['g']),所以就是P2 = ((r+s)%n) * sk * g,接下来的操作不难看出,这里就是两个点相加,这里可以print出来看一下输出,是一个点的坐标的十六进制表示的字符串的拼接,x就是这个点的x坐标。最后是一个判断 r == ((e + x) % self.n)
首先e是固定的 b’Hello, Welcome to ByteCTF2020!’。我们能操作的就是r和s了,x是一个算出来的坐标,为了让这个判断成立,我们就需要构造我们的输入r,为了构造r得提前算出P1的x坐标,而P1=P1+P2 = s * g + ((r + s)%n) * sk * g。乍一看我们好像陷入了死锁。这里头怎么又出现了r?
其中p,q是大数N的一个分解。这里阶的确定不是很严格,但先试试啦。那么要这么试的话就要分解N,那就要看到这个keygen的过程了,这里p,q的生成有一点点小要求,然后就是这个e的生成,为了生成这个e,还特意整了个x,y。最后要求gcd(e, (p+1) * (q+1)),唉,这,感觉我的猜测是对的好叭。到了这里,,这还不像西湖论剑的那一道题嘛Wake me until May ends。这道题相关的paper提到
e,N=(,) c = continued_fraction(e/N) for i in range(len(c)): y=c.numerator(i) x=c.denominator(i) ify == 0: continue T = e*x//y-N-1
if1023<(int(T).bit_length()) < 1026: #根据T的bit位数来确定x,y print(T) print(x,int(x).bit_length()) print(y,int(y).bit_length()) break from gmpy2 import * #Factoring with high bits known _p = (T+iroot(T^2-4*N,int(2))[0])//2
p = int(_p) n=N kbits = 430 PR.<x> = PolynomialRing(Zmod(n)) f = x + p x0 = f.small_roots(X=2^kbits, beta=0.4)[0] p = p+x0 print("p: ", p) assert n % p == 0 q = n/int(p) print("q: ", q)
x,y=(,)
#-d*x*^2 +y^2 = 1+d*x^2*y^2
d = (1-y^2)*inverse_mod(-x^2*y^2-x^2,N)%N #计算系数d e_inv = inverse_mod(int(e),int((int(p)+1)*(int(q)+1))) #计算私钥prikey
def add(ct,pt): #重复倍加算法的实现 ct = ( int((ct[0] * pt[1] + ct[1] * pt[0]) * inverse_mod(1 + d * ct[0] * pt[0] * ct[1] * pt[1], N) % N), int((ct[1] * pt[1] + d * ct[0] * pt[0]) * inverse_mod(1 - d * ct[0] * pt[0] * ct[1] * pt[1], N) % N) ) return ct def mul_by_double_adding(ct,n): pt = (0, 1) while n > 0: if n % 2 == 1: pt = add(ct, pt) ct = add(ct, ct) n = n>>1 returnpt (x,y)=mul_by_double_adding((x,y),e_inv) #获取mt,得到flag from Crypto.Util.number import long_to_bytes print(long_to_bytes(x)+long_to_bytes(y))
import os from Crypto.Cipher import AES from Crypto.Util.strxor importstrxor from Crypto.Util.number import long_to_bytes, bytes_to_long class Toy_AE(): def __init__(self): self.block_size = 16 self.n_size = self.block_size self.delta = b'\x00' * self.block_size self.init_cipher() def init_cipher(self): key = os.urandom(16) self.cipher = AES.new(key = key, mode = AES.MODE_ECB)
def pad(self, m, block_size): return m if len(m) == block_size else (m + b'\x80' + (b'\x00' * (block_size - 1 - len(m))))
def GF2_mul(self, a, b, n_size): s = 0 for bit in bin(a)[2:]: s = s << 1 ifbit == '1': s ^= b upper = bytes_to_long(long_to_bytes(s)[:-n_size]) lower = bytes_to_long(long_to_bytes(s)[-n_size:]) return upper ^ lower
def encrypt(self, msg): return self.A_EF(msg) def decrypt(self, ct, _te): msg, te = self.A_DF(ct) return msg if _te == te else None
def A_EF(self, msg): self.Sigma = b'\x00' * self.n_size self.L = self.cipher.encrypt(b'ConvenienceFixed') self.delta = b'DeltaConvenience' m = len(msg) // self.n_size m += 1if (len(msg) % self.n_size) else0 M_list = [msg[i * self.n_size : (i + 1) * self.n_size] for i in range(m)] C_list = [] for i in range(0, (m-1)//2): C1, C2 = self.feistel_enc_2r(M_list[2*i], M_list[2*i +1]) C_list.append(C1) C_list.append(C2) self.Sigma = strxor(M_list[2*i +1], self.Sigma) self.L = long_to_bytes(self.GF2_mul(2, bytes_to_long(self.L), self.n_size)) if m & 1 == 0: Z = self.cipher.encrypt(strxor(self.L, M_list[-2])) Cm = strxor(Z[:len(M_list[-1])], M_list[-1]) Cm_1 = strxor(self.cipher.encrypt(strxor(strxor(self.L, self.delta), self.pad(Cm, self.block_size))), M_list[-2]) self.Sigma = strxor(self.Sigma, strxor(Z, self.pad(Cm, self.block_size))) self.L = strxor(self.L, self.delta) C_list.append(Cm_1) C_list.append(Cm) else: Cm = strxor(self.cipher.encrypt(self.L)[:len(M_list[-1])], M_list[-1]) self.Sigma = strxor(self.Sigma, self.pad(M_list[-1], self.n_size)) C_list.append(Cm) if len(M_list[-1]) == self.n_size: multer = strxor(long_to_bytes(self.GF2_mul(3, bytes_to_long(self.L), self.n_size)), self.delta) else: multer = long_to_bytes(self.GF2_mul(3, bytes_to_long(self.L), self.n_size)) TE = self.cipher.encrypt(strxor(self.Sigma, multer)) return b''.join(C_list), TE
def A_DF(self, ct): self.Sigma = b'\x00' * self.n_size self.L = self.cipher.encrypt(b'ConvenienceFixed') self.delta = b'DeltaConvenience' m = len(ct) // self.n_size m += 1if (len(ct) % self.n_size) else0 C_list = [ct[i * self.n_size : (i + 1) * self.n_size] for i in range(m)] M_list = [] for i in range(0, (m-1) // 2): M1, M2 = self.feistel_dec_2r(C_list[2*i], C_list[2*i +1]) self.Sigma = strxor(M2 ,self.Sigma) self.L = long_to_bytes(self.GF2_mul(2, bytes_to_long(self.L), self.n_size)) M_list.append(M1) M_list.append(M2) if m & 1 == 0: Mm_1 = strxor(self.cipher.encrypt(strxor(strxor(self.L, self.delta), self.pad(C_list[-1], self.block_size))), C_list[-2]) Z = self.cipher.encrypt(strxor(self.L, Mm_1)) Mm = strxor(Z[:len(C_list[-1])], C_list[-1]) self.Sigma = strxor(self.Sigma, strxor(Z, self.pad(C_list[-1], self.block_size))) self.L = strxor(self.L, self.delta) M_list.append(Mm_1) M_list.append(Mm) else: Mm = strxor(self.cipher.encrypt(self.L)[:len(C_list[-1])], C_list[-1]) self.Sigma = strxor(self.Sigma, self.pad(Mm, self.block_size)) M_list.append(Mm) if len(C_list[-1]) == self.n_size: multer = strxor(long_to_bytes(self.GF2_mul(3, bytes_to_long(self.L), self.n_size)), self.delta) else: multer = long_to_bytes(self.GF2_mul(3, bytes_to_long(self.L), self.n_size)) TE = self.cipher.encrypt(strxor(self.Sigma, multer)) return b''.join(M_list), TE
#!/usr/bin/env python3 import os import random import string from hashlib import sha256
from Toy_AE import Toy_AE from secret import FLAG
defproof_of_work(): random.seed(os.urandom(8)) proof = b''.join([random.choice(string.ascii_letters + string.digits).encode() for _ in range(20)]) digest = sha256(proof).hexdigest().encode() print("sha256(XXXX+%s) == %s" % (proof[4:],digest)) print("Give me XXXX:") x = input().encode() returnFalseif len(x) != 4or sha256(x + proof[4:]).hexdigest().encode() != digest elseTrue
defpack(uid, uname, token, cmd, appendix): r = b'' r += b'Uid=%d\xff' % uid r += b'UserName=%s\xff' % uname r += b'T=%s\xff' % token r += b'Cmd=%s\xff' % cmd r += appendix return r