def challenge44(): p = 0x800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1 q = 0xf4f47f05794b256174bba6e9b396a7707e563c5b g = 0x5958c9d3898b224b12672c0b98e06c60df923cb8bc999d119458fef538b8fa4046c8db53039db620c094c9fa077ef389b5322a559946a71903f990f1f7e0e025e2d7f7cf494aff1a0470f5b64c36b625a097f1651fe775323556fe00b3608c887892878480e99041be601a62166ca6894bdd41a7054ec89f756ba9fc95302291 y = 0x2d026f4bf30195ede3a088da85e398ef869611d0f68f0713d51c9c1a3a26c95105d915e2d8cdf26d056b86b8a7b85519b1c23cc3ecdc6062650462e3063bd179c2a6581519f674a61f1d89a1fff27171ebc1b93d4dc57bceb7ae2430f98a6a4d83d8279ee65d71c1203d2c96d65ebbf7cce9d32971c3de5084cce04a2e147821 with open('44.txt') as f: lines = [line.strip('\n\r').encode() for line in f.readlines()] data = [] for i in range(0, len(lines), 4): msg = lines[i][5:] s = int(lines[i + 1][3:]) r = int(lines[i + 2][3:]) digest = int(lines[i + 3][3:], 16) data.append({'message': msg, 'signature': (s, r), 'digest': digest}) for item1, item2 in itertools.combinations(data, 2): m1 = item1['digest'] m2 = item2['digest'] s1, r1 = item1['signature'] s2, r2 = item2['signature'] k = (m1 - m2) % q * util.modinv((s1 - s2) % q, q) % q x1 = (s1 * k - m1) * util.modinv(r1, q) % q x2 = (s2 * k - m2) * util.modinv(r2, q) % q if x1 == x2 and y == pow(g, x1, p): return x1 raise RuntimeError('Cannot find solution')
def decrypt(c1, c2, c3, n1, n2, n3): """ Decrypt by executing a Low Public Exponent Attack based on the Chinese Remainder Theorem. For a good explanation: http://crypto.stackexchange.com/questions/6713/low-public-exponent-attack-for-rsa """ t1 = c1 * (n2 * n3) * util.modinv(n2 * n3, n1) t2 = c2 * (n1 * n3) * util.modinv(n1 * n3, n2) t3 = c3 * (n1 * n2) * util.modinv(n1 * n2, n3) cubed = (t1 + t2 + t3) % (n1 * n2 * n3) return util.iroot(cubed, 3)
def rsa_keygen(n): # choose random primes p,q on the order of n / 2 bits p = primegen(n // 2) q = primegen(n // 2) # compute N as product of p,q N = p*q # compute phi(n) pN = (p - 1) * (q - 1) # choose public exponent e: # must be relatively prime with phi(N) e = 3 while gcd(pN, e) != 1: e += 1 # compute private exponent d: # the multiplicative inverse of e, modulo phi(N) d = modinv(e, pN) while d < 0: # we want a positive value for d; working modulo phi(N), d += pN # all values d_i = d + k*phi(N) for integer k are equivalent # return the components of RSA key return (e, d, N)
def factorise(n, e, d, bobe): N = e * d - 1 f = 0 t = 0 while N % 2 == 0: f = f + 1 N = N // 2 while True: a = randint(2, n - 1) l = 0 b = pow(a, N, n) bb = pow(b, 2, n) while bb != 1: b = bb bb = pow(bb, 2, n) if b == -1: continue else: t = b p = gcd(t + 1, n) q = gcd(t - 1, n) if p == 1 or q == 1: continue break phi = (p - 1) * (q - 1) if bobe != 0: bobd = modinv(bobe, phi) else: bobd = 0 return p, q, bobd
def challenge43(): def sign(priv, message): x, p, q, g = priv r = pow(g, k, p) % q if r == 0: return None if isinstance(message, int): message = util.from_bytes(message) elif not isinstance(message, (bytes, bytearray)): raise ValueError('Message should be int or bytes') H = util.from_bytes(hashlib.sha1(message).digest()) s = (util.modinv(k, q) * (H + x * r)) % q return r, s p = 0x800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1 q = 0xf4f47f05794b256174bba6e9b396a7707e563c5b g = 0x5958c9d3898b224b12672c0b98e06c60df923cb8bc999d119458fef538b8fa4046c8db53039db620c094c9fa077ef389b5322a559946a71903f990f1f7e0e025e2d7f7cf494aff1a0470f5b64c36b625a097f1651fe775323556fe00b3608c887892878480e99041be601a62166ca6894bdd41a7054ec89f756ba9fc95302291 y = 0x84ad4719d044495496a3201c8ff484feb45b962e7302e56a392aee4abab3e4bdebf2955b4736012f21a08084056b19bcd7fee56048e004e44984e2f411788efdc837a0d2e5abb7b555039fd243ac01f0fb2ed1dec568280ce678e931868d23eb095fde9d3779191b8c0299d6e07bbb283e6633451e535c45513b2d33c99ea17 r = 548099063082341131477253921760299949438196259240 s = 857042759984254168557880549501802188789837994940 H = 0xd2d0714f014a9784047eaeccf956520045c45265 message = b'''For those that envy a MC it can be hazardous to your health So be friendly, a matter of life and death, just like a etch-a-sketch ''' assert H == util.from_bytes(hashlib.sha1(message).digest()) for k in range(0, 2**16 + 1): if util.egcd(k, q)[0] != 1: continue x = (s * k - H) * util.modinv(r, q) % q priv = x, p, q, g if sign(priv, message) == (r, s): return x raise RuntimeError('Cannot find x')
def gen_rsa_special_vuln(filename, bits, clientnum): n, p, q, d = [], [], [], [] e = 3 for _ in range(clientnum): while True: try: nn, pp, qq = _getNPQ(bits) dd = modinv(e, (pp - 1) * (qq - 1)) n.append(nn) p.append(pp) q.append(qq) d.append(dd) except: continue break with open(filename, "w") as file: file.write(F"e ={e}\n") _print_arr(filename, "n", n) _print_arr(filename, "d", d) _print_arr(filename, "p", p) _print_arr(filename, "q", q) _print_arr(filename, "sign_n", n) _print_arr(filename, "sign_d", d)
def decrypt(c1, c2, e1, e2, n): # Compute GCD (gcd, x, y) = util.egcd(e1, e2) assert(gcd == 1) # One of (x, y) will be negative, which makes it difficult to do (c ^ x) % n # To solve that problem, we compute the modular inverse d of c such that: # d ^ (-x) === c ^ x (mod n) if x < 0: c1 = util.modinv(c1, n) x = -x elif y < 0: c2 = util.modinv(c2, n) y = -y # TODO(Use knowledge of c1, c2, x, y to solve for m) pass
def MOgetKeys(p): while True: try: e = randint(2, p - 1) d = modinv(e, p - 1) except: continue break return e, d
def point_double(x, y, p, A): if x == 0 and y == 1: return 0, 1 k = ((3 * x**2 + A) * modinv(2 * y, p)) % p x3 = (k**2 - 2 * x) % p y3 = (k * (x - x3) - y) % p return x3, y3
def sign(priv, message): x, p, q, g = priv k = random.randint(2, q - 1) r = pow(g, k, p) % q if isinstance(message, int): message = util.from_bytes(message) elif not isinstance(message, (bytes, bytearray)): raise ValueError('Message should be int or bytes') H = util.from_bytes(hashlib.sha1(message).digest()) s = (util.modinv(k, q) * (H + x * r)) % q return r, s
def sign(self, msg, generator): """Sign with ElGamal signature.""" r, s = 0, 0 while s == 0: k = randkeyRP(1, Constants.P - 2) r = powm(generator, k) s = (msg_hash(msg, sha1) - self.pri_key * r) * modinv( k, Constants.P - 1) s %= Constants.P - 1 return (r, s)
def decrypt(c1, c2, c3, n1, n2, n3): """ Decrypt by executing a Low Public Exponent Attack based on the Chinese Remainder Theorem. For a good explanation: http://crypto.stackexchange.com/questions/6713/low-public-exponent-attack-for-rsa """ # Here's one step of the recurrence for you... t1 = c1 * (n2 * n3) * util.modinv(n2 * n3, n1) # Can you finish the rest? t2 = t3 =
def _prove_simple(sock, gamma, r, s, g=Constants.G, p=Constants.P, q=Constants.Q): assert (len(r) == len(s)) n = len(r) # step 1 t = recv(sock) # step 2 r_hat = [(r[i] - t) % q for i in range(n)] s_hat = [(s[i] - gamma * t) % q for i in range(n)] theta = [0] + [randkey(0, q - 1) for _ in range(2 * n - 1)] Theta = [] for i in range(2 * n): if i < n: exp = (theta[i] * r_hat[i]) % q exp -= (theta[i + 1] * s_hat[i]) % q exp %= q Theta.append(powm(g, exp, p)) else: exp = (theta[i] * gamma) % q exp -= theta[(i + 1) % (2 * n)] exp %= q Theta.append(powm(g, exp, p)) send(sock, Theta) # step 3 c = recv(sock) # step 4 alpha = [c] tmp = c for i in range(2 * n - 1): if i < n: tmp = (tmp * divide(r_hat[i], s_hat[i], q)) % q alpha.append((tmp + theta[i + 1]) % q) elif i == n: inv = modinv(gamma, q) tmp = (c * powm(inv, (2 * n - 1) - i, q)) % q alpha.append((tmp + theta[i + 1]) % q) else: tmp = (tmp * gamma) % q alpha.append((tmp + theta[i + 1]) % q) send(sock, alpha)
def gen_rsa_one_n(filename, bits): n, p, q = _getNPQ(bits) n = Decimal(n) d = randint(int((Decimal(1) / Decimal(3)) * Decimal(n).sqrt().sqrt()), int(n - (Decimal(1) / Decimal(3)) * Decimal(n).sqrt().sqrt())) while True: try: e = modinv(d, (p - 1) * (q - 1)) except: d = randint( int((Decimal(1) / Decimal(3)) * Decimal(n).sqrt().sqrt()), int(n - (Decimal(1) / Decimal(3)) * Decimal(n).sqrt().sqrt())) continue break dd = randint(int((Decimal(1) / Decimal(3)) * Decimal(n).sqrt().sqrt()), int(n - (Decimal(1) / Decimal(3)) * Decimal(n).sqrt().sqrt())) while True: try: ee = modinv(dd, (p - 1) * (q - 1)) except: dd = randint( int((Decimal(1) / Decimal(3)) * Decimal(n).sqrt().sqrt()), int(n - (Decimal(1) / Decimal(3)) * Decimal(n).sqrt().sqrt())) continue break n = int(n) with open(filename, "w") as file: pass _print_arr(filename, "e", [e, ee]) with open(filename, "a") as file: file.write(F"n = \"{hex(n)[2:]}\"\n") _print_arr(filename, "d", [d, dd]) with open(filename, "a") as file: file.write(F"p = \"{hex(p)[2:]}\"\n") file.write(F"q = \"{hex(q)[2:]}\"\n")
def verify(pub, message, signature): y, p, q, g = pub r, s = signature if not (0 <= r < q and 0 <= s < q): raise ValueError('Invalid signature value') if isinstance(message, int): message = util.from_bytes(message) elif not isinstance(message, (bytes, bytearray)): raise ValueError('Message should be int or bytes') H = util.from_bytes(hashlib.sha1(message).digest()) w = util.modinv(s, q) u1 = (H * w) % q u2 = (r * w) % q v = (pow(g, u1, p) * pow(y, u2, p) % p) % q return v == r
def point_add(x1, y1, x2, y2, p, A): if x1 == 0 and y1 == 1: return x2, y2 if x2 == 0 and y2 == 1: return x1, y1 if x1 == x2 and y1 == y2: return point_double(x1, y1, p, A) if x1 == x2: return 0, 1 k = 1 k = (((y2 - y1) % p) * modinv(((x2 - x1) % p), p)) % p x3 = (k**2 - x1 - x2) % p y3 = (k * (x1 - x3) - y1) % p return x3, y3
def gen_rsa_wiener_vuln(filename, bits): n, p, q = _getNPQ(bits) n = Decimal(n) d = randint(0x10001, int((Decimal(1) / Decimal(3)) * Decimal(n).sqrt().sqrt())) while True: try: e = modinv(d, (p - 1) * (q - 1)) except: d = randint( 0x10001, int((Decimal(1) / Decimal(3)) * Decimal(n).sqrt().sqrt())) continue break n = int(n) _print_params(filename, e, n, d, p, q, n, d)
def sign(priv, message): x, p, q, g = priv r = None for _ in range(5 * q): k = random.randint(2, q-1) r = pow(g, k, p) % q if r != 0: break else: raise RuntimeError('Cannot find a valid r') if isinstance(message, int): message = util.from_bytes(message) elif not isinstance(message, (bytes, bytearray)): raise ValueError('Message should be int or bytes') H = util.from_bytes(hashlib.sha1(message).digest()) s = (util.modinv(k, q) * (H + x*r)) % q return r, s
def ELGSignAdd(filename, x, a, p, r): def gen_k(r): k = randint(2, r - 2) while gcd(k, r - 1) != 1: k = randint(2, r - 2) return k with open(filename, "rb") as file: data = file.read() m = int(sha256(data).hexdigest(), 16) % r k = gen_k(r) w = pow(a, k, p) s = ((m - (x * w) % r) * modinv(k, r)) % r return w, s
def __init__(self, p, q, msg_bytes): self.p = p self.q = q self.N = self.p * self.q self.phiN = (self.p - 1) * (self.q - 1) self.e = 3 self.d = modinv(self.e, self.phiN) k = self.N - 1 self.N_bytes = 0 while k > 0: k >>= 1 self.N_bytes += 1 self.N_bytes = (self.N_bytes + 7) // 8 self.msg_bytes = msg_bytes self.padding_bytes = self.N_bytes - self.msg_bytes - 3 self.oracle_calls = 0
def challenge45(): def gen_key_pair(L=1024, N=160): q = util.gen_prime(N) # gen p left, right = util.bit_range(L) left = (left + q - 1) // q right //= q p = None k = None for _ in range(5 * (right - left)): k = random.randint(left, right) p = k * q + 1 if util.is_probable_prime(p): break else: raise RuntimeError('Cannot find a valid p') # gen g x = random.randint(1, q - 1) y = pow(g, x, p) return (y, p, q, g), (x, p, q, g) def sign(priv, message): x, p, q, g = priv k = random.randint(2, q - 1) r = pow(g, k, p) % q if isinstance(message, int): message = util.from_bytes(message) elif not isinstance(message, (bytes, bytearray)): raise ValueError('Message should be int or bytes') H = util.from_bytes(hashlib.sha1(message).digest()) s = (util.modinv(k, q) * (H + x * r)) % q return r, s def verify(pub, message, signature): y, p, q, g = pub r, s = signature if not (0 <= r < q and 0 <= s < q): raise ValueError('Invalid signature value') if isinstance(message, int): message = util.from_bytes(message) elif not isinstance(message, (bytes, bytearray)): raise ValueError('Message should be int or bytes') H = util.from_bytes(hashlib.sha1(message).digest()) w = util.modinv(s, q) u1 = (H * w) % q u2 = (r * w) % q v = (pow(g, u1, p) * pow(y, u2, p) % p) % q return v == r g = 0 pub, priv = gen_key_pair() message1 = b'Hello, world' message2 = b'Goodbye, world' signature = sign(priv, message1) assert verify(pub, message2, signature) p = 0x800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1 q = 0xf4f47f05794b256174bba6e9b396a7707e563c5b g = p + 1 x = random.randint(1, q - 1) y = pow(g, x, p) z = random.randint(2, 100) r = pow(y, z, p) % q s = r * util.modinv(z, q) % q verify((y, p, q, g), message1, (r, s)) verify((y, p, q, g), message2, (r, s))
def million_tests(): for i in range(100): p = random_prime(2**256) a = randint(1, p) assert modinv(a, p) == inverse_mod(a, p)
T__x, T__y = T_x, T_y a__, b__ = a_, b_ while True: # 5.1 -- one step j = T_x % L T_x, T_y = crv.point_add(T_x, T_y, Rs[j][0], Rs[j][1], p, A) a_ = (a_ + a_arr[j]) % q b_ = (b_ + b_arr[j]) % q # 5.2 -- two steps j = T__x % L T__x, T__y = crv.point_add(T__x, T__y, Rs[j][0], Rs[j][1], p, A) a__ = (a__ + a_arr[j]) % q b__ = (b__ + b_arr[j]) % q j = T__x % L T__x, T__y = crv.point_add(T__x, T__y, Rs[j][0], Rs[j][1], p, A) a__ = (a__ + a_arr[j]) % q b__ = (b__ + b_arr[j]) % q if T_x == T__x and T_y == T__y: break if a_ == a__ and b_ == b__: print("Sorry, try again.") exit(-1) else: d = ((a_-a__) * modinv((b__ - b_)%q, q))%q print(hex(d))
def new_announcement(self, s, msg_args): """Handles a request to carry out one step of the announcement phase. generator: Generator for this server to use. ann_list_pre: Announcement list before the previous server's modifications. ann_list_post: Announcement list after the previous server's modifications. g_, h_: Verifiable shuffle parameters init_id: The id of the server that was the first in the ring. """ generator, ann_list_pre, ann_list_post, g_, h_, init_id = msg_args ann_list = ann_list_post if init_id != self.server_id: if init_id == Constants.INIT_ID: init_id = self.server_id ann_list = [] ann_list.append(list(self.ltp_list.keys())) ann_list.append([(self.secret, v) for v in self.ltp_list.values()]) else: # verify shuffle from prev server if not shuffle.verify(s, ann_list_pre, ann_list_post, g_, h_): eprint(self.name, 'Verifiable shuffle failed.') s.close() return s.close() # update announcement list secret_inv = modinv(powm(self.secret, self.pri_key)) new_ann_list = self.announcement_fwd(ann_list, secret_inv) # shuffle announcement list n = len(new_ann_list[0]) pi = shuffle.generate_permutation(n) new_ann_list = [shuffle.shuffle(elts, pi) for elts in new_ann_list] # update generator and parameters new_generator = powm(generator, self.eph_key) beta = 1 g_ = 1 h_ = secret_inv # pass announcement list to next server s = socket.socket() s.connect(self.next_addr) send(s, [ Constants.NEW_ANNOUNCEMENT, new_generator, ann_list, new_ann_list, g_, h_, init_id ]) # prove shuffle to next server (if more than one server) if self.addr != self.next_addr: shuffle.prove(s, ann_list, new_ann_list, pi, beta, g_, h_) else: # verify shuffle from prev server (if more than one server) if self.addr != self.prev_addr: if not shuffle.verify(s, ann_list_pre, ann_list_post, g_, h_): eprint(self.name, 'Verifiable shuffle failed.') s.close() return s.close() # initialize add announcement stp_list = list(zip(ann_list[0], [rep for sec, rep in ann_list[1]])) stp_args = [stp_list, generator, Constants.INIT_ID] self.replace_stp(stp_args)
def unblind(s, r, n): """Unblind signature `s` that was blinded with random factor `r` under modulus `n`.""" # We need r^{-1}, so we have to solve for modular inverse r_prime = util.modinv(r, n) return (s * r_prime) % n