crypto_computing/week4.py

131 lines
3.5 KiB
Python

# 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
import time
from math import pow
import numpy as np
from crypto.week1 import BloodType, convert_from_string_to_enum, blood_cell_compatibility_lookup
convert_bloodtype_to_index = {
BloodType.O_NEGATIVE: 0,
BloodType.O_POSITIVE: 1,
BloodType.A_NEGATIVE: 2,
BloodType.A_POSITIVE: 3,
BloodType.B_NEGATIVE: 4,
BloodType.B_POSITIVE: 5,
BloodType.AB_NEGATIVE: 6,
BloodType.AB_POSITIVE: 7,
}
class ElGamal:
def __init__(self, g, q):
self.gen_ = g
self.order = q
self.pk = None
self.sk = None
def gen_key(self):
key = SystemRandom().randint(1, self.order)
while np.gcd(q, key) != 1:
key = SystemRandom().randint(1, self.order)
return key
def gen(self, sk):
h = (self.gen_**sk) % self.order
self.sk = sk
self.pk = (self.gen_, h)
return self.pk
def enc(self, m, pk):
# sample random r \in Zq
r = SystemRandom().randint(1, q)
g, h = pk
s = (h**r) % q
p = (g**r) % q
c = s * m
return c, p
def dec(self, c):
c1, c2 = c
# c, p, key, q
h = (c2**self.sk) % q
m = c1 / h
return m
def ogen(self, r):
# Here, q = 2p+1, thus we actually need to use the p here, instead of
# self.order, but as we do not know p yet, .e we
# TODO: Use p instead of self.order, s.t. self.order = 2p+1
s = SystemRandom().randint(1, self.order)
h = s**2 % self.order
return self.gen_, h
class Alice:
def __init__(self, bloodtype, elgamal):
self.elgamal = elgamal
self.gen_ = 9
self.order = 453
self.b = convert_bloodtype_to_index[convert_from_string_to_enum[bloodtype]]
self.sk = SystemRandom().randint(1, self.order)
self.pk = self.elgamal.gen(self.sk)
self.fake_pks = [self.elgamal.ogen(SystemRandom().randint(0, self.order))
for _ in range(7)]
def send_pks(self):
all_pks = self.fake_pks
all_pks.insert(self.b, self.pk)
return all_pks
def retrieve(self, ciphers):
mb = self.elgamal.dec(ciphers[self.b])
return mb
class Bob:
def __init__(self, bloodtype, elgamal):
self.bloodtype = convert_from_string_to_enum[bloodtype]
self.truth_vals = []
self.elgamal = elgamal
self.pks = None
for donor in BloodType:
truth_val = blood_cell_compatibility_lookup(self.bloodtype, donor)
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
if __name__ == "__main__":
p = 199
q = 2*p + 1
g = SystemRandom().randint(2, q)
elgamal = ElGamal(g, q)
sk = elgamal.gen_key()
m = 7
pk = elgamal.gen(sk)
c = elgamal.enc(m, pk)
print(c)
d_m = elgamal.dec(c)
print("decrupted:", d_m)