def gen_DSA_primes(L, N, seedlen, Hash, outlen): acceptable_pairs = [(1024, 160), (2048, 224), (2048, 256), (3072, 256)] if (L, N) not in acceptable_pairs: return False, None, None if seedlen < N: return False, None, None n = int(math.ceil(float(L) / float(outlen)) - 1) b = L - 1 - n * outlen while True: domain_parameter_seed = utils.string_to_integer(os.urandom(seedlen / 8)) U = utils.string_to_integer(Hash(utils.integer_to_string(domain_parameter_seed))) % 2 ** (N - 1) q = 2 ** (N - 1) + U + 1 - (U % 2) if not is_prime(q): continue offset = 1 for counter in range(4 * L): V = {} for j in range(n + 1): V[j] = utils.string_to_integer(Hash(utils.integer_to_string((domain_parameter_seed + offset + j) % 2 ** seedlen))) W = sum([V[j] * 2 ** (j * outlen) for j in range(n - 1)]) + (V[n] % 2 ** b) * 2 ** (n * outlen) X = W + 2 ** (L - 1) c = X % (2 * q) p = X - (c - 1) if p < 2 ** (L - 1): offset = offset + n + 1 continue if is_prime(p): return True, p, q offset = offset + n + 1 return False, None, None
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 RSASSA_PKCS1_v1_5_SIGN(n, d, M): k = (len(bin(n)[2:]) + 7) / 8 # Length of n in octets try: EM = EMSA_PKCS1_v1_5_ENCODE(M, k) except: raise Exception("RSA modulus too short") m = utils.string_to_integer(EM) s = utils.RSA_decrypt(m, n, d) S = utils.integer_to_string(s) return S
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_gen_per_user_keys(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)) x = c % (q - 1) + 1 y = pow(g, x, p) return True, x, y
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 forge_signature(data, n, e): k = (len(bin(n)[2:]) + 7) / 8 b = 8 * k H = SHA256_HASH(data) ASN1_GOOP = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20" D = utils.string_to_integer(ASN1_GOOP + H) N = 2 ** 416 - D # 32 (HASH) + 19 (ASN1_GOOP) + 1 (\x00) = 52 ---> 416 bits X = b - 440 # N * 2^X < 2^(b - 15 - 8) (Need 8 bits padding "\xff" at least), and need multiple of 8. MAX_GARBAGE = 2 ** X - 1 # By picking MAX_GARBAGE as high as possible, we are most likely to find a cube root # whose cube is within the range that starts with the desired bytes. MAX_S3 = 2 ** (b - 15) - N * 2 ** X + MAX_GARBAGE s = cube_root(MAX_S3) return utils.integer_to_string(s, k)
def forge_signature(data, n, e): k = (len(bin(n)[2:]) + 7) / 8 b = 8 * k H = SHA256_HASH(data) ASN1_GOOP = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20" D = utils.string_to_integer(ASN1_GOOP + H) N = 2**416 - D # 32 (HASH) + 19 (ASN1_GOOP) + 1 (\x00) = 52 ---> 416 bits X = b - 440 # N * 2^X < 2^(b - 15 - 8) (Need 8 bits padding "\xff" at least), and need multiple of 8. MAX_GARBAGE = 2**X - 1 # By picking MAX_GARBAGE as high as possible, we are most likely to find a cube root # whose cube is within the range that starts with the desired bytes. MAX_S3 = 2**(b - 15) - N * 2**X + MAX_GARBAGE s = cube_root(MAX_S3) return utils.integer_to_string(s, k)
def check_signature_weak(n, e, M, S): k = (len(bin(n)[2:]) + 7) / 8 # Length of n in octets if len(S) != k: return False s = utils.string_to_integer(S) m = pow(s, e, n) try: EM = utils.integer_to_string(m, k) except: return False H = SHA256_HASH(M) ASN1_GOOP = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20" T = ASN1_GOOP + H if re.match("\x00\x01" + "[\xff]+" + "\x00" + re.escape(T), EM): return True return False
def RSASSA_PKCS1_v1_5_VERIFY(n, e, M, S): k = (len(bin(n)[2:]) + 7) / 8 # Length of n in octets if len(S) != k: return False s = utils.string_to_integer(S) m = pow(s, e, n) try: EM_ = utils.integer_to_string(m, k) except: return False try: EM = EMSA_PKCS1_v1_5_ENCODE(M, k) except: raise Exception("RSA modulus too short") if EM == EM_: return True return False
def DSA_gen_signature(p, q, g, x, M, Hash, outlen): N = len(bin(q)[2:]) while True: status, k, k_inv = gen_DSA_per_message_secret(p, q) 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 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
def double_plaintext(cipher, n, e): c = utils.string_to_integer(cipher) c = (c * pow(2, e, n)) % n return utils.integer_to_string(c)
def Bleichenbacher_attack(server, ciphertext, n, e): k = (len(bin(n)[2:].strip('L')) + 7) / 8 B = 2 ** (8 * (k - 2)) c = utils.string_to_integer(ciphertext) # Step 1 (skip blinding) si = 1 c0 = c Mi = [[2 * B, 3 * B - 1]] i = 1 while True: si_1 = si Mi_1 = Mi # Step 2 if i == 1: # Step 2.a si = (n + 3 * B - 1) / (3 * B) # ceil(n / (3B)) while server.padding_oracle(utils.integer_to_string((c0 * pow(si, e, n)) % n)) != True: si += 1 elif len(Mi) >= 2: # Step 2.b si = si_1 + 1 while server.padding_oracle(utils.integer_to_string((c0 * pow(si, e, n)) % n)) != True: si += 1 else: # Step 2.c a = Mi[0][0] b = Mi[0][1] ri = (2 * b * si_1 - 2 * B + n - 1) / n # ceil((2 * b * si_1 - 2 * B) / n) conforming = False while not conforming: for si in range((2 * B + ri * n + b - 1) / b, (3 * B - 1 + ri * n) / a + 1): if server.padding_oracle(utils.integer_to_string((c0 * pow(si, e, n)) % n)) == True: conforming = True break else: ri += 1 # Step 3 Mi = [] for Ir in Mi_1: a = Ir[0] b = Ir[1] for r in range((a * si - 3 * B + 1 + n - 1) / n, (b * si - 2 * B) / n + 1): new_a = max(a, (2 * B + r * n + si - 1) / si) # to get the ceiling new_b = min(b, (3 * B - 1 + r * n) / si) if new_b >= new_a: Mi.append([new_a, new_b]) # Step 4 if len(Mi) == 1 and Mi[0][0] == Mi[0][1]: m = Mi[0][0] break i += 1 return PKCS1_v1_5_Unpad(utils.integer_to_string(m, k))