def DSA_gen_signature_weak(p, q, g, x, M, Hash, outlen, k=None): N = len(bin(q)[2:]) # Force k to specific value to test signature generation from recovered secret key x. if k != None: k_inv = utils.invmod(k, q) r = pow(g, k, p) % q z = utils.string_to_integer(Hash(M)[:min(N, outlen) / 8]) s = (k_inv * (z + x * r)) % q return True, r, s while True: status, k, k_inv = gen_DSA_per_message_secret_weak(p, q, g) if status == False: return False, None, None r = pow(g, k, p) % q if r == 0: continue z = utils.string_to_integer( Hash(M)[:min(N, outlen) / 8]) # Leftmost min(N, outlen) bits of Hash(M) s = (k_inv * (z + x * r)) % q if s == 0: continue break return True, r, s
def find_k_from_repeated_sigs(q, sigs): m1 = sigs[0]['m'] m2 = sigs[1]['m'] s1 = sigs[0]['s'] s2 = sigs[1]['s'] k = ((m1 - m2) * utils.invmod(s1 - s2, q)) % q return k
def broadcast_attack(cipher_0, n_0, cipher_1, n_1, cipher_2, n_2): c_0 = int(cipher_0.encode('hex'), 16) c_1 = int(cipher_1.encode('hex'), 16) c_2 = int(cipher_2.encode('hex'), 16) m_s_0 = n_1 * n_2 m_s_1 = n_0 * n_2 m_s_2 = n_0 * n_1 result = (c_0 * m_s_0 * utils.invmod(m_s_0, n_0) + c_1 * m_s_1 * utils.invmod(m_s_1, n_1) + c_2 * m_s_2 * utils.invmod(m_s_2, n_2)) % (n_0 * n_1 * n_2) m = cube_root(result) xM = hex(m)[2:].strip('L') if len(xM) % 2 != 0: xM = '0' + xM return xM.decode('hex')
def gen_fake_DSA_signature(g, p, q, y): if g == 0: return 0, random.randint(0, q - 1) if g == p + 1: z = random.randint(0, q - 1) r = pow(y, z, p) % q s = (r * utils.invmod(z, q)) % q return r, s return None
def gen_DSA_per_message_secret(p, q, g): acceptable_pairs = [(1024, 160), (2048, 224), (2048, 256), (3072, 256)] N = len(bin(q)[2:]) L = len(bin(p)[2:]) if (L, N) not in acceptable_pairs: return False, None, None c = utils.string_to_integer(os.urandom((N + 64) / 8)) k = c % (q - 1) + 1 k_inv = utils.invmod(k, q) return True, k, k_inv
def gen_DSA_per_message_secret_weak(p, q, g): acceptable_pairs = [(1024, 160), (2048, 224), (2048, 256), (3072, 256)] N = len(bin(q)[2:]) L = len(bin(p)[2:]) if (L, N) not in acceptable_pairs: return False, None, None # Generate random k between 1 and 2^16 (weak!) k = random.randint(1, 2**16) k_inv = utils.invmod(k, q) return True, k, k_inv
def gen_DSA_per_message_secret(p, q): acceptable_pairs = [(1024, 160), (2048, 224), (2048, 256), (3072, 256)] N = len(bin(q)[2:]) L = len(bin(p)[2:]) if (L, N) not in acceptable_pairs: return False, None, None c = utils.string_to_integer(os.urandom((N + 64) / 8)) k = c % (q - 1) + 1 k_inv = utils.invmod(k, q) return True, k, k_inv
def DSA_verify_signature(p, q, g, y, M, r, s, Hash, outlen): N = len(bin(q)[2:]) if r <= 0 or r >= q or s <= 0 or s >= q: return False w = utils.invmod(s, q) z = utils.string_to_integer(Hash(M)[:min(N, outlen) / 8]) u1 = (z * w) % q u2 = (r * w) % q v = ((pow(g, u1, p) * pow(y, u2, p)) % p) % q if v == r: return True return False
def DSA_verify_signature(p, q, g, y, M, r, s, Hash, outlen): N = len(bin(q)[2:]) if r <= 0 or r >= q or s <= 0 or s >= q: return False w = utils.invmod(s, q) z = utils.string_to_integer(Hash(M)[: min(N, outlen) / 8]) u1 = (z * w) % q u2 = (r * w) % q v = ((pow(g, u1, p) * pow(y, u2, p)) % p) % q if v == r: return True return False
def recover_plaintext(self): ciphertext = self.client.intercept_ciphertext() self.fetch_pubkey() message = self.submit_ciphertext(ciphertext) if message != None: print "Direct decryption worked... wtf?" return message c = utils.string_to_integer(ciphertext) s = random.randint(2, self.n - 1) new_c = (pow(s, self.e, self.n) * c) % self.n new_ciphertext = utils.integer_to_string(new_c) new_message = self.submit_ciphertext(new_ciphertext) new_p = utils.string_to_integer(new_message) p = (new_p * utils.invmod(s, self.n)) % self.n message = utils.integer_to_string(p) return message
def recover_x_from_k(q, k, r, s, msg, Hash, outlen): N = len(bin(q)[2:]) x = (((s * k) - utils.string_to_integer(Hash(msg)[: min(N, outlen) / 8])) * utils.invmod(r, q)) % q return x