Miller-Rabin prime gen for week4.

This commit is contained in:
Casper 2019-09-22 01:41:39 +02:00
parent d688640a41
commit 2d2a3e7f95
3 changed files with 70 additions and 37 deletions

View File

@ -1,3 +1,3 @@
from .week2 import main from .week4 import main
main() main()

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import random import random
from crypto.week1 import BloodType, blood_cell_compatibility_lookup from .week1 import BloodType, blood_cell_compatibility_lookup
class Protocol: class Protocol:

101
week4.py
View File

@ -1,22 +1,13 @@
# Concept: Create 8 PKs where each represent a bloodtype. Let 7 of them be created by OGen and 1 of them by KeyGen. # Concept: Create 8 PKs where each represent a bloodtype. Let 7 of them be created by OGen and 1 of them by KeyGen.
# The one represents our bloodtype. Bob will then encrypt 8 values using these PKs, where each value repredents # The one represents our bloodtype. Bob will then encrypt 8 values using these PKs, where each value repredents
# A truth value, thus either true or false, s.t. each cipher is an entry in the bloodtype comptability matrix. # A truth value, thus either true or false, s.t. each cipher is an entry in the bloodtype comptability matrix.
import math
import random
from secrets import SystemRandom from secrets import SystemRandom
import numpy as np
from crypto.week1 import BloodType, blood_cell_compatibility_lookup
# We can't encrypt 0, so we have to index from 1 from .week1 import BloodType, blood_cell_compatibility_lookup
convert_bloodtype_to_index = {
BloodType.O_NEGATIVE: 1, bloodtypes = {b: i for i, b in enumerate(BloodType, start=1)} # we can't encrypt 0, so we have to index from 1
BloodType.O_POSITIVE: 2,
BloodType.A_NEGATIVE: 3,
BloodType.A_POSITIVE: 4,
BloodType.B_NEGATIVE: 5,
BloodType.B_POSITIVE: 6,
BloodType.AB_NEGATIVE: 7,
BloodType.AB_POSITIVE: 8,
}
class ElGamal: class ElGamal:
@ -29,7 +20,7 @@ class ElGamal:
def gen_key(self): def gen_key(self):
key = SystemRandom().randint(1, self.order) key = SystemRandom().randint(1, self.order)
while np.gcd(self.order, key) != 1: while math.gcd(self.order, key) != 1:
key = SystemRandom().randint(1, self.order) key = SystemRandom().randint(1, self.order)
return key return key
@ -67,12 +58,8 @@ class Alice:
self.sk = elgamal.gen_key() self.sk = elgamal.gen_key()
self.pk = elgamal.gen(self.sk) self.pk = elgamal.gen(self.sk)
# There is 100% a better way to get the index, also, it's to avoid encryption 0. Coincidentally, it's self.b = bloodtypes[bloodtype]
# not an issue when we do it, as O- is in the 0th index and this bloodtype can donate to everyone self.fake_pks = [self.elgamal.ogen() for _ in range(7)]
# so the decryption bugging, it not an issue
self.b = list(convert_bloodtype_to_index.keys()).index(bloodtype)+1
self.fake_pks = [self.elgamal.ogen()
for _ in range(7)]
def send_pks(self): def send_pks(self):
all_pks = self.fake_pks all_pks = self.fake_pks
@ -80,15 +67,15 @@ class Alice:
return all_pks return all_pks
def retrieve(self, ciphers): def retrieve(self, ciphers):
print(ciphers) #print(ciphers)
mb = self.elgamal.dec(ciphers[self.b-1]) mb = self.elgamal.dec(ciphers[self.b-1])
# Bog sends 1 for false, 2 for true, so we have to subtract 1 here # Bob sends 1 for false, 2 for true, so we have to subtract 1 here
return mb-1 return mb - 1
class Bob: class Bob:
def __init__(self, bloodtype, elgamal): def __init__(self, bloodtype, elgamal):
self.bloodtype = list(convert_bloodtype_to_index.keys()).index(bloodtype) self.bloodtype = bloodtypes[bloodtype]
self.truth_vals = [] self.truth_vals = []
self.elgamal = elgamal self.elgamal = elgamal
self.pks = None self.pks = None
@ -104,16 +91,66 @@ class Bob:
ciphers = [] ciphers = []
for idx, truth_val in enumerate(self.truth_vals): for idx, truth_val in enumerate(self.truth_vals):
pk = self.pks[idx] pk = self.pks[idx]
# Bob can't send 0, as it will encrypt to 0 c = self.elgamal.enc(truth_val + 1, pk) # + 1 since Bob can't send 0, as it will encrypt to 0
c = self.elgamal.enc(truth_val+1, pk)
ciphers.append(c) ciphers.append(c)
return ciphers return ciphers
def run(donor : BloodType, recipient : BloodType): def is_prime(n: int, k: int) -> bool:
p = 15485863 """
Miller-Rabin Primality test.
Adapted from pseudo-code at https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test.
:param n: An odd integer to be tested for primality.
:param k: The number of rounds of testing to perform.
:return: True if n is 'probably prime', False otherwise if n is composite.
"""
# write n as 2r·d + 1 with d odd (by factoring out powers of 2 from n 1)
d = n - 1
r = 0
while d % 2 == 0:
d >>= 1
r += 1
for i in range(k): # witnessLoop
continue_wl = False
a = random.randint(2, n - 2)
x = pow(a, d, n)
if x == 1 or x == n - 1:
continue
for j in range(r - 1):
x = pow(x, 2, n)
if x == n - 1:
continue_wl = True
break
if continue_wl:
continue
return False
return True
def gen_prime(b: int, k: int = 10) -> int:
"""
Generate strong probable prime by drawing integers at random until one passes the is_prime test.
Adapted from pseudo-code at https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test.
:param b: The number of bits of the result.
:param k: The number of rounds of testing to perform.
:return: a strong probable prime.
"""
while True:
n = random.randint(2**(b-1), (2**b)-1)
if n % 2 == 0:
continue
if is_prime(n, k):
return n
def run(donor: BloodType, recipient: BloodType):
p = gen_prime(128)
q = 2 * p + 1 q = 2 * p + 1
g = SystemRandom().randint(2, q) g = SystemRandom().randint(2, q)
#print("p:", p, "q:", q, "g:", g)
elgamal = ElGamal(g, q, p) elgamal = ElGamal(g, q, p)
alice = Alice(donor, elgamal) alice = Alice(donor, elgamal)
@ -125,11 +162,7 @@ def run(donor : BloodType, recipient : BloodType):
return bool(pls) return bool(pls)
if __name__ == "__main__": def main():
#z = run(BloodType.O_POSITIVE, BloodType.A_NEGATIVE)
#print(z)
#exit()
green = 0 green = 0
red = 0 red = 0
for i, recipient in enumerate(BloodType): for i, recipient in enumerate(BloodType):