from Crypto.Util.number import getPrime, bytes_to_long from random import randint import os
FLAG = os.getenv("FLAG").encode() flag1 = FLAG[:15] flag2 = FLAG[15:]
defcrypto1(): p = getPrime(1024) q = getPrime(1024) n = p * q e = 0x10001 x1=randint(0,2**11) y1=randint(0,2**114) x2=randint(0,2**11) y2=randint(0,2**514) hint1=x1*p+y1*q-0x114 hint2=x2*p+y2*q-0x514 c = pow(bytes_to_long(flag1), e, n) print(n) print(c) print(hint1) print(hint2)
defcrypto2(): p = getPrime(1024) q = getPrime(1024) n = p * q e = 0x10001 hint = pow(514*p - 114*q, n - p - q, n) c = pow(bytes_to_long(flag2),e,n) print(n) print(c) print(hint) print("==================================================================") crypto1() print("==================================================================") crypto2() print("==================================================================")
首先解crypto1
hint1=x1∗p+y1∗q−0x11
hint2=x2∗p+y2∗q−0x514
hint1+0x114≡x1∗pmodq
hint2+0x514≡x2∗pmodq
令H1=hint1+0x1144,H2=hint2+0x514
x2H1≡x1H2modq
由于x1和x2很小,直接爆破
再解crypto2,开始在hint = pow(514*p - 114*q, n - p - q, n)卡住了,后面想到
hint=(514∗p−114∗q)n−p−qmodn
其中n−p−q=φ(n)−1
xn−p−q≡xφ(n)−1≡x−1≡hintmodn
通过计算模逆元B并构建方程组求解
n=p∗q514p−114q=hint−1modn
from math import isqrt,gcd from gmpy2 import invert
import os from Crypto.Util.number import * defgiaogiao(hex_string): base_num = 0x6c62272e07bb014262b821756295c58d x = 0x0000000001000000000000000000013b MOD = 2**128 for i in hex_string: base_num = (base_num * x) & (MOD - 1) base_num ^= i return base_num
giao=201431453607244229943761366749810895688
print("1geiwoligiaogiao") hex_string = int(input(),16) s = long_to_bytes(hex_string)
if giaogiao(s) == giao: print(os.getenv('FLAG')) else: print("error")
对一个自定义的类hash函数,尝试了很久逆算法,应该要用格
# sage TARGET = 201431453607244229943761366749810895688 h0 = 0x6c62272e07bb014262b821756295c58d p = 0x0000000001000000000000000000013b MOD = 2**128
n = 16 M = Matrix.column([p^(n - i - 1) for i inrange(n)] + [-(TARGET - h0*p^n), MOD]) M = M.augment(identity_matrix(n+1).stack(vector([0] * (n+1)))) Q = Matrix.diagonal([2^128] + [2^4] * n + [2^8]) M *= Q M = M.BKZ() M /= Q for r in M: if r[0] == 0andabs(r[-1]) == 1: r *= r[-1] good = r[1:-1] print(good) break inp = [] y = int(h0*p) t = (h0*p^n + good[0] * p^(n-1)) % MOD for i inrange(n): for x inrange(256): y_ = (int(y) ^^ int(x)) * p^(n-i-1) % MOD if y_ == t: print('good', i, x) inp.append(x) if i < n-1: t = (t + good[i+1] * p^(n-i-2)) % MOD y = ((int(y) ^^ int(x)) * p) % MOD break else: print('bad', i) print(bytes(inp).hex()) # 020101081b04390001051a020a3d0f0f
import ctypes from random import getrandbits import signal import socketserver from sympy import nextprime import numpy as np from Crypto.Util.number import * import ast
defhandle(self): signal.signal(signal.SIGALRM, self.timeout_handler) signal.alarm(40) self.dosend("welcome to my crypto system!") delta = 1184 beta = 256 tau = 704 self.m = getrandbits(beta) self.dilithium = Dilithium()
p = self.generate_prime(delta) q = self.generate_prime(delta) N = [p * q] ROUND = 25 for _ inrange(ROUND): d = getrandbits(704) N.append((p + d) * (q + d)) self.dosend("N = " + str(N)) s1, s2 = self.get_sk() s1 = np.array([i for j in s1 for i in j]) s2 = np.array([i for j in s2 for i in j]) H = [] for i inrange(ROUND * ROUND): tmp = np.array(self.generate_coefs(32, 1024)) H.append(int(tmp.dot(s1) % self.dilithium.Q )) tmp = np.array(self.generate_coefs(32, 1024)) H.append(int(tmp.dot(s2) % self.dilithium.Q))
self.dosend("this is your hint!") self.dosend("H = " + str(H)) self.dosend("another gift: you can choose one message to sign") m = int(self.recvline("m: ")) signature = self.dilithium.sign_message(long_to_bytes(m)) assert self.dilithium.verify_sign(long_to_bytes(m), signature) self.dosend("this is your signature") self.dosend("sinature = " + signature.hex()) num = self.generate_coefs(4, 1)[0] self.dosend("you need to give me some signatures in hex format!") signatures = ast.literal_eval(self.recvline("signatures: ")) assertlen(list(set(signatures))) == len(signatures) answers = sum([self.dilithium.verify_sign(long_to_bytes(self.m), bytes.fromhex(sinature.zfill(len(signature) + len(signature)%2))) for sinature in signatures]) if answers == num: self.dosend("congrats! you got the flag!") withopen("flag.txt") as f: self.dosend(f.read()) else: self.dosend("sorry, you failed!") exit()
defdistribution(self, lbound, rbound, dim): return [randint(lbound, rbound) for _ inrange(dim)]
deflwe_encrypt(self, message): a = self.distribution(0, lwe_ciphertext_modulus - 1, self.lwe_dim) e = self.distribution(-15, 15, 1)[0] return a, sum([a[i] * self.lwe_secret_key[i] for i inrange(self.lwe_dim)]) + message + e * lwe_plaintext_modulus
deflwe_keygen(self): A = [] B = [] for _ inrange(self.lwe_num_samples): sample = self.lwe_encrypt(0) A.append(sample[0]) B.append(sample[1]) return A, B
whileTrue: monomials = [x^i for i inrange(self.rlwe_dim + 1)] c = self.distribution(0, self.rlwe_modulus - 1, self.rlwe_dim) + [1] f = sum([c[i] * monomials[i] for i inrange(self.rlwe_dim + 1)]) PR = P.quo(f) if f.is_irreducible(): break a = self.distribution(0, self.rlwe_modulus - 1, self.rlwe_dim) e = self.distribution(-5, 5, self.rlwe_dim) s = [flag[i] for i inrange(len(flag))] b = PR(a) * PR(s) + PR(e) return a, b, f, self.rlwe_modulus