crypto_computing/week4.py

138 lines
3.8 KiB
Python
Raw Normal View History

2019-09-18 14:09:36 +00:00
# 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
# A truth value, thus either true or false, s.t. each cipher is an entry in the bloodtype comptability matrix.
from secrets import SystemRandom
2019-09-18 14:09:36 +00:00
import numpy as np
from crypto.week1 import BloodType, convert_from_string_to_enum, blood_cell_compatibility_lookup
# We can't encrypt 0, so we have to index from 1
2019-09-18 14:09:36 +00:00
convert_bloodtype_to_index = {
BloodType.O_NEGATIVE: 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,
2019-09-18 14:09:36 +00:00
}
class ElGamal:
def __init__(self, g, q, p):
2019-09-18 14:09:36 +00:00
self.gen_ = g
self.order = q
self.p = p
2019-09-18 14:09:36 +00:00
self.pk = None
self.sk = None
def gen_key(self):
key = SystemRandom().randint(1, self.order)
2019-09-18 16:14:19 +00:00
while np.gcd(self.order, key) != 1:
key = SystemRandom().randint(1, self.order)
return key
2019-09-18 14:09:36 +00:00
def gen(self, sk):
h = (self.gen_**sk) % self.order
2019-09-18 14:09:36 +00:00
self.sk = sk
self.pk = (self.gen_, h)
return self.pk
def enc(self, m, pk):
# sample random r \in Zq
2019-09-18 16:14:19 +00:00
r = SystemRandom().randint(1, self.order)
2019-09-18 14:09:36 +00:00
g, h = pk
2019-09-18 16:14:19 +00:00
s = (h**r) % self.order
p = (g**r) % self.order
c = s * m
return c, p
2019-09-18 14:09:36 +00:00
def dec(self, c):
c1, c2 = c
2019-09-18 16:14:19 +00:00
h = (c2**self.sk) % self.order
m = c1 / h
2019-09-18 14:09:36 +00:00
return m
def ogen(self):
s = SystemRandom().randint(1, self.order)
2019-09-18 14:09:36 +00:00
h = s**2 % self.order
return self.gen_, h
class Alice:
def __init__(self, bloodtype, elgamal):
self.elgamal = elgamal
self.sk = elgamal.gen_key()
self.pk = elgamal.gen(self.sk)
2019-09-18 16:14:19 +00:00
self.b = list(convert_bloodtype_to_index.keys()).index(bloodtype)+1
self.fake_pks = [self.elgamal.ogen()
2019-09-18 14:09:36 +00:00
for _ in range(7)]
def send_pks(self):
all_pks = self.fake_pks
all_pks.insert(self.b-1, self.pk)
2019-09-18 14:09:36 +00:00
return all_pks
def retrieve(self, ciphers):
mb = self.elgamal.dec(ciphers[self.b-1])
2019-09-18 14:09:36 +00:00
return mb
class Bob:
def __init__(self, bloodtype, elgamal):
2019-09-18 16:14:19 +00:00
self.bloodtype = list(convert_bloodtype_to_index.keys()).index(bloodtype)
2019-09-18 14:09:36 +00:00
self.truth_vals = []
self.elgamal = elgamal
self.pks = None
for donor in BloodType:
2019-09-18 16:14:19 +00:00
truth_val = blood_cell_compatibility_lookup(bloodtype, donor)
2019-09-18 14:09:36 +00:00
self.truth_vals.append(truth_val)
def receive_pks(self, pks):
self.pks = pks
def transfer_messages(self):
ciphers = []
for idx, truth_val in enumerate(self.truth_vals):
pk = self.pks[idx]
c = self.elgamal.enc(truth_val, pk)
ciphers.append(c)
return ciphers
2019-09-18 16:14:19 +00:00
def run(donor : BloodType, recipient : BloodType):
p = 199
2019-09-18 16:14:19 +00:00
q = 2 * p + 1
g = SystemRandom().randint(2, q)
elgamal = ElGamal(g, q, p)
2019-09-18 16:14:19 +00:00
alice = Alice(donor, elgamal)
bob = Bob(recipient, elgamal)
bob.receive_pks(alice.send_pks())
pls = alice.retrieve(bob.transfer_messages())
2019-09-18 16:14:19 +00:00
return bool(pls)
2019-09-18 14:09:36 +00:00
2019-09-18 16:14:19 +00:00
if __name__ == "__main__":
# 199 is a large prime
green = 0
red = 0
for i, recipient in enumerate(BloodType):
for j, donor in enumerate(BloodType):
z = run(donor, recipient)
lookup = blood_cell_compatibility_lookup(recipient, donor)
if lookup == z:
green += 1
else:
print(f"'{BloodType(donor).name} -> {BloodType(recipient).name}' should be {lookup}.")
red += 1
print("Green:", green)
print("Red :", red)