def test_asymmetric_encrypt_decrypt(algorithm_name, generate_keypair, encrypt, decrypt, iterations=1024, plaintext_size=32): print("Beginning {} unit test".format(algorithm_name)) print("Validating correctness...") for count in range(iterations): public_key, private_key = generate_keypair() message = random_integer(plaintext_size) ciphertext = encrypt(message, public_key) plaintext = decrypt(ciphertext, private_key) if plaintext != message: raise Warning("Unit test failed after {} successful tests".format(count)) print("...done") test_encrypt_decrypt_time(iterations, encrypt, decrypt, public_key, private_key, plaintext_size) m1, m2 = 3, 6 ciphertext1 = encrypt(m1, public_key) ciphertext2 = encrypt(m2, public_key) test_for_homomorphism(ciphertext1, ciphertext2, decrypt, private_key, m1, m2) public_sizes = determine_key_size(public_key) private_sizes = determine_key_size(private_key) print("Public key size : {}".format(sum(public_sizes))) print("Private key size: {}".format(sum(private_sizes))) print("Ciphertext size : {}".format(size_in_bits(encrypt(random_integer(32), public_key)))) print("(sizes are in bits)") print("{} unit test passed".format(algorithm_name))
def generate_public_parameters(security_level=SECURITY_LEVEL): a = random_integer(security_level * 3) b = random_integer(security_level) q = random_integer((security_level * 3) + 4) assert a < q shift = ((security_level * 3)) * 8 return a, b, q, shift
def generate_private_key(security_level=SECURITY_LEVEL): p_size = security_level * 3 p = big_prime(p_size + 1) a_i = random_integer((security_level * 2) + 1) >> 7 # adds 1 extra bit b_i = random_integer(security_level) ab_i = (a_i * b_i) % p return a_i, b_i, ab_i, p
def generate_parameters(a_size=A_SIZE, b_size=B_SIZE, x_size=X_SIZE, y_size=Y_SIZE): a = random_integer(a_size) b = random_integer(b_size) x = random_integer(x_size) y = big_prime(y_size) return a, b, x, y
def encapsulate_key(public_key, public_points=POINTS, security_level=SECURITY_LEVEL): s1 = random_integer(security_level) ciphertext = (public_key * s1) for point in public_points: s = random_integer(security_level) ciphertext += (point * s) return ciphertext, s1
def generate_public_key(private_key, security_level=SECURITY_LEVEL): a = modular_inverse((2, private_key * big_prime(security_level)) b = modular_inverse((3, private_key * big_prime(security_level)) return a, b def generate_keypair(security_level=SECURITY_LEVEL): private_key = generate_private_key(security_level) public_key = generate_public_key(private_key, security_level) return public_key, private_key def encapsulate_key(public_key, security_level=SECURITY_LEVEL): a, b = public_key s1 = random_integer(security_level) s2 = random_integer(security_level) e = random_integer(security_level) shared_secret = (3 * s1) + (2 * s2) + (6 * e) ciphertext = ((a * s1) + (b * s2) + e) return ciphertext, shared_secret def recover_key(ciphertext, private_key): return (ciphertext * 6) % private_key def unit_test(): from unittesting import test_key_exchange test_key_exchange("knowninverses", generate_keypair, encapsulate_key, recover_key, iterations=10000) if __name__ == "__main__": unit_test()
def encrypt(m, key, r_size=16, n=N): p0, p1, p2, k, ki = key q0 = random_integer(r_size) q1 = (p2 * random_integer(r_size)) + m # 50 bytes if p2 == 33, r == 16, m adds +1 ciphertext = (p0 * q0) + (p1 * q1) # 16 + 50 = 66 + 32 = 98 ciphertext = (ciphertext * k) % n return ciphertext
def encapsulate_key(public_key, security_level=SECURITY_LEVEL, shift=(SECURITY_LEVEL * 2 * 8) + 32): e = random_integer(security_level * 3) ciphertext = e + sum(number * random_integer(security_level) for number in public_key) return ciphertext, e >> shift
def generate_public_key(private_key, r_size=R_SIZE, x_size=X_SIZE): ai, q = private_key r = random_integer(r_size) x = random_integer(x_size) a = modular_inverse(ai, q) # print log(ai, 2), log(q, 2), log(r, 2), log(x, 2) return a, (q * r) + x
def encapsulate_key(public_key, s_size=S_SIZE, e_size=E_SIZE, mask=MASK): a, q_r = public_key s = random_integer(s_size) e = random_integer(e_size) # assert (a * s) + e > q_r # print log(a, 2), log(q_r, 2), log(s, 2), log(e, 2), (log(a, 2) + log(s, 2)) - log(q_r, 2) return ((a * s) + e) % q_r, s & mask
def test_encrypt_decrypt(): key = generate_key() c0 = encrypt(0, key) c1 = encrypt(1, key) r = random_integer(SECURITY_LEVEL) cr = encrypt(r, key) p0 = decrypt(c0, key) p1 = decrypt(c1, key) pr = decrypt(cr, key) assert p0 == 0 assert p1 == 1 assert pr == r r2 = random_integer(SECURITY_LEVEL) cr2 = encrypt(r2, key) add(cr, cr2) assert decrypt(cr, key) == (r + r2) % MODULUS cr[:] = mul(cr, cr2, key) assert decrypt(cr, key) == ((r + r2) * r2) % MODULUS cr[:] = mul(cr, cr, key) assert decrypt(cr, key) == (((r + r2) * r2) ** 2) % MODULUS
def test_encrypt_decrypt(): key = generate_key() c0 = encrypt(0, key) c1 = encrypt(1, key) r = random_integer(SECURITY_LEVEL) cr = encrypt(r, key) p0 = decrypt(c0, key) p1 = decrypt(c1, key) pr = decrypt(cr, key) assert p0 == 0 assert p1 == 1 assert pr == r r2 = random_integer(SECURITY_LEVEL) cr2 = encrypt(r2, key) add(cr, cr2) assert decrypt(cr, key) == (r + r2) % MODULUS cr[:] = mul(cr, cr2, key) assert decrypt(cr, key) == ((r + r2) * r2) % MODULUS cr[:] = mul(cr, cr, key) assert decrypt(cr, key) == (((r + r2) * r2)**2) % MODULUS
def encapsulate_key(public_key, s_size=S_SIZE, e_size=E_SIZE): """ usage: encapsulate_key(public_key, s_size=S_SIZE, e_size=E_SIZE) => ciphertext, key Returns a ciphertext, key tuple. """ a, modulus = public_key s = random_integer(s_size) e = random_integer(e_size) return ((a * s) + e) % modulus, s
def encapsulate_key(public_key, s_size=S_SIZE, e_size=E_SIZE, shift=SHIFT, mask=MASK): """ usage: encapsulate_key(public_key, s_size=S_SIZE, e_size=E_SIZE) => ciphertext, key Returns a ciphertext, key tuple. """ a, modulus = public_key s = random_integer(s_size) e = random_integer(e_size) return ((a * s) + (e << shift)) % modulus, s & mask
def generate_key(p_size=P_SIZE, k_size=K_SIZE, n=N): p_0 = random_integer(p_size) p_1 = random_integer(p_size * 2) p_2 = random_integer(p_size * 3) k = (n - random_integer(k_size)) k_i = modular_inverse(k, n) return ([p_0, p_1, p_2], k, k_i)
def test_output_distribution(): p = 255 outputs = [] for q_count in range(256): for e_count in range(256): outputs.append((p * random_integer(1)) + random_integer(1)) _outputs = set(outputs) print len(_outputs), _outputs
def generate_parameters(a_size=A_SIZE, b_size=B_SIZE, x_size=X_SIZE, p_size=P_SIZE): a = random_integer(a_size) b = random_integer(b_size) x = random_integer(x_size) p = big_prime(p_size) z = modular_inverse(modular_subtraction(1, a, p), p) return a, b, x, p, z
def encrypt(m, key, r_size=16, n=N): p0, p1, p2, k, ki = key q0 = random_integer(r_size) q1 = (p2 * random_integer(r_size) ) + m # 50 bytes if p2 == 33, r == 16, m adds +1 ciphertext = (p0 * q0) + (p1 * q1) # 16 + 50 = 66 + 32 = 98 ciphertext = (ciphertext * k) % n return ciphertext
def encapsulate_key(public_key, security_level=SECURITY_LEVEL): ciphertext = 0 #sum((public_key[count] * random_integer(security_level) for count in range(security_level))) for count in range(security_level): public_key_element = public_key[count] ciphertext += (public_key_element * random_integer(security_level)) e = random_integer(security_level) ciphertext += e return ciphertext, e
def encrypt(m, key, r_size=32, n=N): p, k, k_i = key ciphertext = ((p[0] * m) + # 520 bits (p[1] * random_integer(r_size)) + # 528 + 256 = 784 (p[2] * random_integer(r_size))) # 792 + 256 = 1048 assert ciphertext < n ciphertext = (k * ciphertext) % n return ciphertext
def generate_public_key(private_key, b_size=8, c_size=8, x_size=8, p=P): ai, y = private_key a = modular_inverse(ai, p) x = random_integer(x_size) b = random_integer(b_size) c = random_integer(c_size) public_key = (((a * x) + b) % p, ((a * y) + c) % p) return public_key
def exchange_key(public_key, s_size=13, e_size=25, p=P): """ usage: exchange_key(public_key, s_size=32, e_size=32, p=P) => ciphertext, secret Returns a ciphertext and a shared secret. The ciphertext should be delivered to the holder of the associated private key, so that they may recover the shared secret. """ s = random_integer(s_size) ciphertext = (public_key * s) + random_integer(e_size) return ciphertext % p, s
def generate_private_key(parameters=PARAMETERS): ab_size = parameters["ab_size"] while True: a = random_integer(ab_size) b = random_integer(ab_size) if not is_prime(pow(a, 2) + pow(b, 2)): break return a, b
def exchange_key(public_key, s_size=16, e_size=16, p=P): """ usage: exchange_key(public_key, s_size=32, e_size=32, p=P) => ciphertext, secret Returns a ciphertext and a shared secret. The ciphertext should be delivered to the holder of the associated private key, so that they may recover the shared secret. """ s = random_integer(s_size) ciphertext = (public_key * s) + random_integer(e_size) return ciphertext % p, s
def generate_public_key(private_key, points=POINTS, security_level=SECURITY_LEVEL): a, b = points x, y = private_key e1, e2 = random_integer(security_level * 2), random_integer( security_level * 2) return ((a * x) + (b * y) + e1, (a * y) + (b * x) + e2)
def encrypt(m, public_key, e_size=E_SIZE, s_size=S_SIZE, shift=SHIFT, modulus=MODULUS): """ usage: encrypt(m, public_key, e_size=E_SIZE, s_size=S_SIZE,, shift=SHIFT, modulus=MODULUS) => ciphertext Returns a ciphertext integer. """ e = (m << shift) | random_integer(e_size) ciphertext = e + sum(number * random_integer(s_size) for number in public_key) return ciphertext % modulus
def encrypt(m, key, r_size=32, n=N): p, k, k_i = key ciphertext = ((p[0] * m) + (p[1] * random_integer(r_size)) + (p[2] * random_integer(r_size))) assert ciphertext < n ciphertext = (k * ciphertext) % n return ciphertext
def encrypt(m, secret_key, x_size=X_SIZE, e_size=E_SIZE, e_shift=E_SHIFT, q=Q): encryption_key, decryption_key = secret_key a, b, ab = encryption_key x = random_integer(x_size) y = random_integer(x_size) e = random_integer(e_size) e |= m << e_shift ciphertext = ((a * x) + (b * y) + (ab * e)) % q return ciphertext
def generate_public_key(private_key, b_size=32, c_size=32, p=P): a = modular_inverse(private_key, p) b = random_integer(b_size) c = random_integer(c_size) print format(a, 'b').zfill(256)[:80] print format((a + b) % p, 'b').zfill(256)[:80] print format((a + c) % p, 'b').zfill(256)[:80] public_key = ((a + b) % p, (a + c) % p) return public_key
def encapsulate_key(public_key, parameters=PARAMETERS): p = parameters["p"] s = random_integer(parameters["s_size"]) r = random_integer(parameters["r_size"]) shared_secret = pow(parameters["generator"], s, p) encrypted_secret = scalar_exponentiation(public_key[0], s, p) randomizer = scalar_exponentiation(public_key[1], r, p) ciphertext = multiply(encrypted_secret, randomizer, p) return ciphertext, shared_secret
def generate_public_key(private_key, e_size=E_SIZE, error_size=ERROR_SIZE, a=A, shift=SHIFT_AMOUNT): s = private_key e = random_integer(e_size) r = random_integer(error_size) return (s * (a + (e << shift))) + (r << shift)
def generate_public_parameters(security_level=SECURITY_LEVEL): inverse_size, q_size, s_size, r_size, z_size, mask, shift = generate_parameter_sizes(security_level) inverse = 1 << (inverse_size * 8) assert inverse == (2 ** (inverse_size * 8)) q = random_integer(q_size) while log(q, 2) < ((q_size * 8) - .1): q = random_integer(q_size) return inverse, q
def generate_secret_key(parameters=PARAMETERS, q=Q): inverse_size = parameters["inverse_size"] inverse_shift = parameters["inverse_shift"] ai = (random_integer(inverse_size) << inverse_shift) + 1 bi = (random_integer(inverse_size) << inverse_shift) + 1 d = (ai * bi) % q a = modular_inverse(ai, q) b = modular_inverse(bi, q) return Key_Tuple((a, b), d)
def generate_private_key(short_inverse_size=24, p=P): """ usage: generate_private_key(short_inverse_size=65, p=P) => private_key Returns 1 integer, suitable for use as a private key. """ short_inverse = random_integer(short_inverse_size) a = modular_inverse(short_inverse, p) b = random_integer(11) c = random_integer(11) return short_inverse, a, b, c
def generate_private_key(short_inverse_size=17, p=P): """ usage: generate_private_key(short_inverse_size=65, p=P) => private_key Returns 1 integer, suitable for use as a private key. """ short_inverse = random_integer(short_inverse_size) a = modular_inverse(short_inverse, p) b = random_integer(short_inverse_size - 1) c = random_integer(short_inverse_size - 1) return short_inverse, a, b, c
def generate_secret_key(parameters=PARAMETERS, q=Q): inverse_size = parameters["inverse_size"] inverse_shift = parameters["inverse_shift"] ai = (random_integer(inverse_size) << inverse_shift) + 1 bi = (random_integer(inverse_size) << inverse_shift) + 1 d = (ai * bi) % q a = modular_inverse(ai, q) b = modular_inverse(bi, q) return a, b, d
def generate_public_key(private_key, security_level=SECURITY_LEVEL, public_key_size=PUBLIC_KEY_SIZE, e=lambda size: random_integer(size)): si, modulus = private_key s = modular_inverse(si, modulus) a = random_integer(security_level) return [(s * (a + e(security_level))) % modulus for count in range(public_key_size)]
def generate_public_key(private_key, points=POINTS, security_level=SECURITY_LEVEL): """ usage: generate_public_key(private_key, points=POINTS, security_level=SECURITY_LEVEL) => public_key Returns the integer(s) that constitute a public key. """ s = private_key s2 = random_integer(security_level) e = random_integer(security_level + (security_level / 2)) a, b = points return (a * s) + (b * s2) + e
def generate_public_key(private_key, security_level=SECURITY_LEVEL, public_key_size=PUBLIC_KEY_SIZE): ai, modulus = private_key public_key = [] while len(public_key) < public_key_size: try: public_key.append(modular_inverse(ai, modulus * random_integer(security_level)) + modular_inverse(ai, modulus * random_integer(security_level))) except ValueError: continue return public_key
def generate_private_key(inverse_size=INVERSE_SIZE, p_size=P_SIZE): while True: inverse = random_integer(inverse_size) modulus = random_integer(p_size) try: modular_inverse(inverse, modulus) except ValueError: continue else: break return inverse, modulus
def generate_private_key(security_level=SECURITY_LEVEL): while True: short_inverse = random_integer((security_level * 2) + 3) modulus = random_integer((security_level * 3) + 5) try: modular_inverse(short_inverse, modulus) except ValueError: continue else: break return short_inverse, modulus