class TestDiffieHellman(unittest.TestCase): def setUp(self): self.alice = DiffieHellman() self.bob = DiffieHellman() def test_equality_of_keys(self): self.alice.generate_public_key() self.bob.generate_public_key() alices_shared_key = self.alice.generate_shared_secret(self.bob.public_key) bobs_shared_key = self.bob.generate_shared_secret(self.alice.public_key) self.assertEqual(alices_shared_key, bobs_shared_key, "There is a mismatch between two shared secrets. Both shared secrets should be the same. This is bad.") def test_decorators_private_key(self): self.alice.generate_public_key() self.assertIn("_DiffieHellman__private_key", self.alice.__dict__) def test_generate_private_key(self): self.alice.generate_private_key() self.assertIn("_DiffieHellman__private_key", self.alice.__dict__) def test_generate_public_key(self): self.alice.generate_public_key() self.assertIn("public_key", self.alice.__dict__) def test_verify_public_key(self): self.alice.generate_public_key() self.bob.generate_public_key() self.assertTrue(self.alice.verify_public_key(self.bob.public_key)) self.assertFalse(self.alice.verify_public_key(2)) self.assertFalse(self.alice.verify_public_key(self.alice.prime - 1))
class TestDiffieHellman(unittest.TestCase): def setUp(self): self.alice = DiffieHellman() self.bob = DiffieHellman() def test_equality_of_keys(self): self.alice.generate_public_key() self.bob.generate_public_key() alices_shared_key = self.alice.generate_shared_secret( self.bob.public_key) bobs_shared_key = self.bob.generate_shared_secret( self.alice.public_key) self.assertEqual( alices_shared_key, bobs_shared_key, "There is a mismatch between two shared secrets. Both shared secrets should be the same. This is bad." ) def test_decorators_private_key(self): self.alice.generate_public_key() self.assertIn("_DiffieHellman__private_key", self.alice.__dict__) def test_generate_private_key(self): self.alice.generate_private_key() self.assertIn("_DiffieHellman__private_key", self.alice.__dict__) def test_generate_public_key(self): self.alice.generate_public_key() self.assertIn("public_key", self.alice.__dict__) def test_verify_public_key(self): self.alice.generate_public_key() self.bob.generate_public_key() self.assertTrue(self.alice.verify_public_key(self.bob.public_key)) self.assertFalse(self.alice.verify_public_key(2)) self.assertFalse(self.alice.verify_public_key(self.alice.prime - 1))
class Sender: def __init__(self): self._sock_to_receiver = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock_to_mb = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._df = DiffieHellman() self._df.generate_private_key() self._df.generate_public_key() self._session_key = None self._k = None self._k_rand = None def connect(self, address): """ The sender(S) in this connect method will attempt to connect to the receiver(R) by a regular sock connection. If the connection is set up successfully, S and R will execute a key exchange protocol then both of them will get a shared secret key. After that three keys (a session key Kssl, a key K used in our detection protocol, and a key Krand used as a seed) will be derived from this secret key. Then, S will try to connect to the middle- box by another regular sock connection. If the connection is set up successfully, S will execute a secure computation with MB so that MB can obtain rules encrypted with key K without knowing K. :param address: the receiver's address :return: """ try: self._sock_to_receiver.connect(address) except socket.error as error: print(f'Could not connect with the receiver: {error}') exit(1) except TypeError as error: print(f'Type error: {error}') exit(1) else: self._key_exchange(self._df.public_key) self._derive_from_secret() print('session key', self._session_key) try: self._sock_to_mb.connect(BLINDBOX_ADDRESS) except socket.error as error: print(f'Could not connect with blindBox: {error}') exit(1) except TypeError as error: print(f'Type error: {error}') exit(1) else: self._rule_preparation() def _key_exchange(self, public_key): """ After a key exchange using Diffie-Hellman algorithm, the sender will agree on a shared secret with the receiver. :param public_key: The sender's public key for key exchange. :return: None """ key_to_bytes = str(public_key).encode() self._sock_to_receiver.sendall(key_to_bytes) data = self._sock_to_receiver.recv(20480) print(f'data received from the receiver {data}') try: pk_from_receiver = int(data) except ValueError: print('Invalid data type!') else: if self._df.verify_public_key(pk_from_receiver): self._df.generate_shared_secret(pk_from_receiver) print('I got the shared key:', self._df.shared_key) else: raise ValueError('Invalid public key from the sender!') def _derive_from_secret(self): """ Use the shared key to derive three keys by using a pseudorandom generator. _session_key: used to encrypt the traffic in the socket. _k: used in the detection protocol _k_rand: used as a seed for randomness. Since both end-points have the same seed, they will generate the same randomness. :return: None """ key_to_bytes = str(self._df.shared_key).encode() randoms = Randoms() self._session_key = derive_key(key_to_bytes, randoms.random1) self._k = derive_key(key_to_bytes, randoms.random2) self._k_rand = derive_key(key_to_bytes, randoms.random3) def _rule_preparation(self): """ Sender will use garbled circuits to compute AES(r,k) with the BlindBox while the sender do not know the rule and the BlindBox do not know the key k. :return: """ key_numbers = int(self._sock_to_mb.recv(1024)) for i in range(key_numbers): output = subprocess.getoutput(OBLIVC_AES_PATH + "/a.out 1235 -- " + self._k.decode()) while output == "TCP accept failed": output = subprocess.getoutput(OBLIVC_AES_PATH + "/a.out 1235 -- " + self._k.decode()) def send(self, data): encrypted_data = aes_encrypt(data.encode(), self._session_key) self._sock_to_mb.sendall(encrypted_data) sleep(0.4) tokens = nltk.word_tokenize(data) encrypted_tokens = b'' for token in tokens: encrypted_tokens += dpi_encrypt(token.encode(), self._session_key) encrypted_tokens += b' ' self._sock_to_mb.sendall(encrypted_tokens)
class Receiver: def __init__(self): self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock_to_mb = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock.bind(ADDRESS) self._sock.listen(10) self._df = DiffieHellman() self._df.generate_private_key() self._df.generate_public_key() self._session_key = None self._k = None self._k_rand = None def connection_setup(self): while True: # Wait for a connection connection, address = self._sock.accept() self._key_exchange(connection, self._df.public_key) print('My shared key:', self._df.shared_key) self._derive_from_secret() print('session key', self._session_key) try: self._sock_to_mb.connect(BLINDBOX_ADDRESS) except socket.error as error: print(f'Could not connect with blindBox: {error}') exit(1) except TypeError as error: print(f'Type error: {error}') exit(1) else: self._rule_preparation() def _key_exchange(self, connection, public_key): """ After a key exchange using Diffie-Hellman algorithm, the sender will agree on a shared secret with the receiver. :param public_key: The sender's public key for key exchange. :return: None """ data = connection.recv(20480) print(f'data received from the sender: {data}') try: pk_from_sender = int(data) except ValueError: print('Invalid data type!') else: if self._df.verify_public_key(pk_from_sender): self._df.generate_shared_secret(pk_from_sender) print('I got the shared key:', self._df.shared_key) connection.sendall(str(public_key).encode()) else: raise ValueError('Invalid public key from the sender!') def _derive_from_secret(self): """ Use the shared secret to derive three keys by using a pseudorandom generator. _session_key: used to encrypt the traffic in the socket. _k: used in our detection protocol _k_rand: used as a seed for randomness. Since both end-points have the same seed, they will generate the same randomness. :return: None """ key_to_bytes = str(self._df.shared_key).encode() randoms = Randoms() self._session_key = derive_key(key_to_bytes, randoms.random1) self._k = derive_key(key_to_bytes, randoms.random2) self._k_rand = derive_key(key_to_bytes, randoms.random3) def _rule_preparation(self): """ Sender will use garbled circuits to compute AES(r,k) with the BlindBox while the sender do not know the rule and the BlindBox do not know the key k. :return: """ key_numbers = int(self._sock_to_mb.recv(1024)) for i in range(key_numbers): output = subprocess.getoutput(OBLIVC_AES_PATH + "/a.out 5321 -- " + self._k.decode()) while output == "TCP accept failed": output = subprocess.getoutput(OBLIVC_AES_PATH + "/a.out 5321 -- " + self._k.decode()) def receive(self): encrypted_traffic = self._sock_to_mb.recv(20480) encrypted_tokens = self._sock_to_mb.recv(20480) traffic = aes_decrypt(encrypted_traffic) self.check_tokens(traffic, encrypted_tokens) def check_tokens(self, traffic, encrypted_tokens): pass