diff --git a/.gitignore b/.gitignore index f53cf17..d03f097 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ uploads/*/* client/log.txt venv -.vscode \ No newline at end of file +.vscode +sto.dat \ No newline at end of file diff --git a/p2p/kademlia/first_node.py b/client/etc/first_node.py similarity index 100% rename from p2p/kademlia/first_node.py rename to client/etc/first_node.py diff --git a/p2p/kademlia/test.py b/client/etc/test.py similarity index 100% rename from p2p/kademlia/test.py rename to client/etc/test.py diff --git a/client/main.py b/client/main.py index 7ea9229..c04b3b2 100644 --- a/client/main.py +++ b/client/main.py @@ -36,6 +36,7 @@ from kivy.core.window import Window from kivy.core.text import LabelBase import shutil from kivy.uix.image import Image +from p2p.crypto import * Window.size = WINDOW_SIZE diff --git a/p2p/crypto.py b/client/p2p/crypto.py similarity index 82% rename from p2p/crypto.py rename to client/p2p/crypto.py index f2773f2..60e9d06 100644 --- a/p2p/crypto.py +++ b/client/p2p/crypto.py @@ -27,19 +27,21 @@ def new_keys(save=True): return private_key,public_key -def save_private_key(private_key,fn=PATH_PRIVATE_KEY): +def save_private_key(private_key,fn=PATH_PRIVATE_KEY,return_instead=False): pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption() ) + if return_instead: return pem with open(fn,'wb') as f: f.write(pem) -def save_public_key(public_key,fn=PATH_PUBLIC_KEY): +def save_public_key(public_key,fn=PATH_PUBLIC_KEY,return_instead=False): pem = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) + if return_instead: return pem with open(fn,'wb') as f: f.write(pem) @@ -110,22 +112,22 @@ def verify_msg(message, signature, public_key): -#private_key,public_key = new_keys() -private_key,public_key = load_keys() +# #private_key,public_key = new_keys() +# private_key,public_key = load_keys() -#print(private_key) -#print(public_key) +# #print(private_key) +# #print(public_key) -enc = encrypt_msg('Drive your plow over the bones of the dead', public_key) -#print(enc) +# #enc = encrypt_msg('Drive your plow over the bones of the dead', public_key) +# #print(enc) -dec = decrypt_msg(enc,private_key) -#print(dec) +# dec = decrypt_msg(enc,private_key) +# #print(dec) -msg = b'hello' -signature = sign_msg(msg,private_key) +# msg = b'hello' +# signature = sign_msg(msg,private_key) -#print(encrypt_msg(b'hello',public_key)) +# #print(encrypt_msg(b'hello',public_key)) -print(verify_msg(msg+b'!!',signature,public_key)) \ No newline at end of file +# print(verify_msg(msg+b'!!',signature,public_key)) \ No newline at end of file diff --git a/client/p2p/p2p.py b/client/p2p/p2p.py new file mode 100644 index 0000000..3779d0e --- /dev/null +++ b/client/p2p/p2p.py @@ -0,0 +1,119 @@ +import logging +import asyncio + +from kademlia.network import Server +from kademlia.storage import * +import shelve +from collections import OrderedDict +import pickle,os + +HOST_NODE_PRIME = "128.232.229.63" #"68.66.241.111" + + + +class HalfForgetfulStorage(ForgetfulStorage): + def __init__(self, ttl=604800): + """ + By default, max age is a week. + """ + self.fn='sto.dat' + if not os.path.exists(self.fn): + self.data={} + else: + with open(self.fn,'rb') as f: + self.data=pickle.load(f) + + + print('loaded:',self.data) + + #self.data = pickle.open('sto.dat','rb') #,writeback=True) + # self.data = self.store.get('OrderedDict',OrderedDict()) + self.ttl = ttl + + def __setitem__(self, key, value): + self.data[key] = (time.monotonic(), value) + self.write() + + def write(self): + with open(self.fn,'wb') as f: + pickle.dump(self.data, f, protocol=pickle.HIGHEST_PROTOCOL) + + def get(self, key, default=None): + # self.cull() + print('looking for key: ', key) + if key in self.data: + print('found it!') + return self[key] + return default + + def __getitem__(self, key): + return self.data[key][1] + + def __repr__(self): + return repr(self.data) + + def iter_older_than(self, seconds_old): + min_birthday = time.monotonic() - seconds_old + zipped = self._triple_iter() + matches = takewhile(lambda r: min_birthday >= r[1], zipped) + return list(map(operator.itemgetter(0, 2), matches)) + + def _triple_iter(self): + ikeys = self.data.keys() + ibirthday = map(operator.itemgetter(0), self.data.values()) + ivalues = map(operator.itemgetter(1), self.data.values()) + return zip(ikeys, ibirthday, ivalues) + + def __iter__(self): + ikeys = self.data.keys() + ivalues = map(operator.itemgetter(1), self.data.values()) + return zip(ikeys, ivalues) + + +handler = logging.StreamHandler() +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +handler.setFormatter(formatter) +log = logging.getLogger('kademlia') +log.addHandler(handler) +log.setLevel(logging.DEBUG) + +def start_first_node(): + loop = asyncio.get_event_loop() + loop.set_debug(True) + + + shelf = HalfForgetfulStorage() + + server = Server(storage=shelf) + loop.run_until_complete(server.listen(8468)) + + try: + loop.run_forever() + except KeyboardInterrupt: + pass + finally: + server.stop() + loop.close() + + +def connect(): + # host="0.0.0.0" + + async def run(): + # Create a node and start listening on port 5678 + node = Server(storage=HalfForgetfulStorage()) + await node.listen(8469) + + # Bootstrap the node by connecting to other known nodes, in this case + # replace 123.123.123.123 with the IP of another node and optionally + # give as many ip/port combos as you can for other nodes. + await node.bootstrap([(HOST_NODE_PRIME, 8468)]) + + # set a value for the key "my-key" on the network + #await node.set("my-key2", "my awesome value") + + # get the value associated with "my-key" from the network + result = await node.get("my-key2") + print(result) + + asyncio.run(run())