commit 3c5cd43f8cd0b7d36f706d2a5fad077afd3cdc1c Author: indigo Date: Tue Jun 8 22:47:09 2021 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92afa22 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +venv/ diff --git a/discovery.py b/discovery.py new file mode 100644 index 0000000..36bd50f --- /dev/null +++ b/discovery.py @@ -0,0 +1,83 @@ +from nacl.public import PrivateKey, PublicKey +import identity +import socket +import sys +from shs import SHSClientCrypto, SHSServerCrypto +import hmac +from hashlib import sha256 + +class Peer(object): + def __init__( + self, + identity: + identity.Identity, + port=8008, + network_id=b'42' + ) -> None: + super().__init__() + self.identity = identity + hostname = socket.gethostname() + self.ip_address = socket.gethostbyname(hostname) + self.port = port + self.ephemeral_keys = None + self.network_id = network_id + + def broadcast(self): + print(f'#TODO: Broadcast net:{self.ip_address}:{self.port}~shs:{self.identity}') + # try: + # s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + # except socket.error: + # print('Failed to create socket') + # sys.exit() + # host = '255.255.255.255' + # port = 55558 + # while True: + # msg = f'net:{self.ip_address}:{self.port}~shs:{self.identity[1:]}' + + def generate_ephemeral_keys(self): + sk = PrivateKey.generate() + pk = sk.public_key + self.ephemeral_keys = {'sk': sk, 'pk': pk} + + def do_handshake(self, role='client'): + self.generate_ephemeral_keys() + if role=='client': + self.client_handshake() + + def client_handshake(self): + # Client knows + # own private/public keys + # ephemeral handshake keys + # server public key from discovery + # network ID + self.send_client_hello() + + def server_handshake(self): + # Server already knows + # own private/public keys + # ephemeral handshake keys + # network ID + self.verify_client_hello() + self.send_server_hello() + + def send_client_hello(self): + nacl_auth = bytearray( + hmac.HMAC(msg=self.ephemeral_keys.get('pk')._public_key, key=self.network_id, digestmod=sha256).digest() + ) + client_ephemeral_pk = bytearray(self.ephemeral_keys.get('pk')._public_key) + return nacl_auth + client_ephemeral_pk + + def verify_client_hello(self, hello_msg: bytearray): + assert(len(hello_msg) == 64) + client_hmac = hello_msg[0:31] + client_ephemeral_pk = hello_msg[32:] + hmac.compare_digest(client_hmac, hmac.new(key=self.network_id, msg=client_ephemeral_pk)) + + def send_server_hello(self): + pass + +if __name__ == '__main__': + client = Peer(identity=identity.Identity()) + server = Peer(identity=identity.Identity()) + client.generate_ephemeral_keys() + print(server.verify_client_hello(client.send_client_hello())) \ No newline at end of file diff --git a/identity.py b/identity.py new file mode 100644 index 0000000..b9dc3d6 --- /dev/null +++ b/identity.py @@ -0,0 +1,22 @@ +from nacl.signing import SigningKey +import base64 + +class Identity(object): + """ + Container for ED25519 keypair + """ + def __init__(self) -> None: + super().__init__() + self.private_key = SigningKey.generate() + self.public_key = self.private_key.verify_key + + # def __str__(self): + # return bytes.decode(base64.b64encode(self.public_key)) + + # def __repr__(self) -> str: + # return self.__str__() + + +if __name__ == '__main__': + alice = Identity() + print(alice) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fdd438e --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pynacl \ No newline at end of file