From bc88e8107c0bdee7405f1bfa17c8a8670a46a26d Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Mon, 7 May 2018 01:55:03 -0500 Subject: [PATCH] work on pow for public keys --- Makefile | 2 +- onionr/api.py | 4 ++-- onionr/communicator.py | 2 +- onionr/core.py | 53 ++++++++++++++++++++++++++---------------- onionr/onionr.py | 3 ++- onionr/onionrcrypto.py | 24 ++++++++++++++++++- onionr/onionrutils.py | 13 ++++++++--- 7 files changed, 72 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 78ff7939..607478ba 100644 --- a/Makefile +++ b/Makefile @@ -30,4 +30,4 @@ soft-reset: reset: @echo "Hard-resetting Onionr..." rm -rf onionr/data/ | true > /dev/null 2>&1 - @./RUN-LINUX.sh version | grep -v "Failed" --color=always + #@./RUN-LINUX.sh version | grep -v "Failed" --color=always diff --git a/onionr/api.py b/onionr/api.py index b6b115a5..5cccb40f 100755 --- a/onionr/api.py +++ b/onionr/api.py @@ -227,8 +227,8 @@ class API: response = 'none' resp = Response(response) elif action == 'kex': - peers = self._core.listPeers() - response = ','.join(self._core.listPeers()) + peers = self._core.listPeers(getPow=True) + response = ','.join(peers) resp = Response(response) else: resp = Response("") diff --git a/onionr/communicator.py b/onionr/communicator.py index 70c4569b..25126b64 100755 --- a/onionr/communicator.py +++ b/onionr/communicator.py @@ -679,7 +679,7 @@ class OnionrCommunicate: except KeyError: return False dataLen = len(blockContent) - print(blockContent) + expectedHash = self._crypto.blake2bHash(base64.b64decode(metadata['powToken']) + self._crypto.blake2bHash(blockContent.encode())) difficulty = 0 try: diff --git a/onionr/core.py b/onionr/core.py index ab315041..91a74014 100644 --- a/onionr/core.py +++ b/onionr/core.py @@ -76,7 +76,7 @@ class Core: exit(1) return - def addPeer(self, peerID, name=''): + def addPeer(self, peerID, powID, name=''): ''' Adds a public key to the key database (misleading function name) @@ -85,10 +85,11 @@ class Core: # This function simply adds a peer to the DB if not self._utils.validatePubKey(peerID): return False + conn = sqlite3.connect(self.peerDB) hashID = self._crypto.pubKeyHashID(peerID) c = conn.cursor() - t = (peerID, name, 'unknown', hashID) + t = (peerID, name, 'unknown', hashID, powID) for i in c.execute("SELECT * FROM PEERS where id = '" + peerID + "';"): try: @@ -99,7 +100,7 @@ class Core: pass except IndexError: pass - c.execute('INSERT INTO peers (id, name, dateSeen, hashID) VALUES(?, ?, ?, ?);', t) + c.execute('INSERT INTO peers (id, name, dateSeen, pow, hashID) VALUES(?, ?, ?, ?, ?);', t) conn.commit() conn.close() @@ -212,7 +213,8 @@ class Core: bytesStored int, trust int, pubkeyExchanged int, - hashID); + hashID text, + pow text not null); ''') conn.commit() conn.close() @@ -431,7 +433,7 @@ class Core: conn.close() return addressList - def listPeers(self, randomOrder=True): + def listPeers(self, randomOrder=True, getPow=False): ''' Return a list of public keys (misleading function name) @@ -448,10 +450,16 @@ class Core: for i in c.execute(payload): try: if len(i[0]) != 0: - peerList.append(i[0]) + if getPow: + peerList.append(i[0] + '-' + i[11]) + else: + peerList.append(i[0]) except TypeError: pass - peerList.append(self._crypto.pubKey) + if getPow: + peerList.append(self._crypto.pubKey + '-' + self._crypto.pubKeyPowToken) + else: + peerList.append(self._crypto.pubKey) conn.close() return peerList @@ -633,19 +641,24 @@ class Core: powProof = onionrproofs.POW(data) powToken = '' # wait for proof to complete - while True: - powToken = powProof.getResult() - if powToken == False: - time.sleep(0.3) - continue - powHash = powToken[0] - powToken = base64.b64encode(powToken[1]) - try: - powToken = powToken.decode() - except AttributeError: - pass - finally: - break + try: + while True: + powToken = powProof.getResult() + if powToken == False: + time.sleep(0.3) + continue + powHash = powToken[0] + powToken = base64.b64encode(powToken[1]) + try: + powToken = powToken.decode() + except AttributeError: + pass + finally: + break + except KeyboardInterrupt: + logger.warn("Got keyboard interrupt while working on inserting block, stopping.") + powProof.shutdown() + return '' try: data.decode() diff --git a/onionr/onionr.py b/onionr/onionr.py index 285c74bf..bec3fad9 100755 --- a/onionr/onionr.py +++ b/onionr/onionr.py @@ -389,7 +389,8 @@ class Onionr: addedHash = self.onionrCore.insertBlock(messageToAdd, header='txt') #self.onionrCore.addToBlockDB(addedHash, selfInsert=True) #self.onionrCore.setBlockType(addedHash, 'txt') - logger.info("Message inserted as as block %s" % addedHash) + if addedHash != '': + logger.info("Message inserted as as block %s" % addedHash) return def getPMs(self): diff --git a/onionr/onionrcrypto.py b/onionr/onionrcrypto.py index 487e192a..d400e8b6 100644 --- a/onionr/onionrcrypto.py +++ b/onionr/onionrcrypto.py @@ -17,15 +17,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' -import nacl.signing, nacl.encoding, nacl.public, nacl.hash, nacl.secret, os, binascii, base64, hashlib, logger +import nacl.signing, nacl.encoding, nacl.public, nacl.hash, nacl.secret, os, binascii, base64, hashlib, logger, onionrproofs, time class OnionrCrypto: def __init__(self, coreInstance): self._core = coreInstance self._keyFile = 'data/keys.txt' + self.keyPowFile = 'data/keyPow.txt' self.pubKey = None self.privKey = None + self.pubKeyPowToken = None + self.pubKeyPowHash = None + self.HASH_ID_ROUNDS = 2000 # Load our own pub/priv Ed25519 keys, gen & save them if they don't exist @@ -34,12 +38,30 @@ class OnionrCrypto: keys = keys.read().split(',') self.pubKey = keys[0] self.privKey = keys[1] + try: + with open(self.keyPowFile, 'r') as powFile: + data = powFile.read() + self.pubKeyPowHash = data.split('-')[0] + self.pubKeyPowToken = data.split('-')[1] + except (FileNotFoundError, IndexError): + pass else: keys = self.generatePubKey() self.pubKey = keys[0] self.privKey = keys[1] with open(self._keyFile, 'w') as keyfile: keyfile.write(self.pubKey + ',' + self.privKey) + with open(self.keyPowFile, 'w') as keyPowFile: + proof = onionrproofs.POW(self.pubKey) + logger.info('Doing necessary work to insert our public key') + while True: + time.sleep(0.2) + powToken = proof.getResult() + if powToken != False: + break + keyPowFile.write(base64.b64encode(powToken[1]).decode()) + self.pubKeyPowToken = powToken[1] + self.pubKeyPowHash = powToken[0] return def edVerify(self, data, key, sig, encodedData=True): diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py index 24e549a3..4e7b05bb 100644 --- a/onionr/onionrutils.py +++ b/onionr/onionrutils.py @@ -101,9 +101,16 @@ class OnionrUtils: retVal = False if newKeyList != False: for key in newKeyList.split(','): - if not key in self._core.listPeers(randomOrder=False) and type(key) != None and key != self._core._crypto.pubKey: - if self._core.addPeer(key): - retVal = True + key = key.split('-') + if len(key[0]) > 60 or len(key[1]) > 1000: + logger.warn(key[0] + ' or its pow value is too large.') + continue + if self._core._crypto.blake2bHash(base64.b64decode(key[1]) + key[0]).startswith('0000'): + if not key[0] in self._core.listPeers(randomOrder=False) and type(key) != None and key[0] != self._core._crypto.pubKey: + if self._core.addPeer(key[0], key[1]): + retVal = True + else: + logger.warn(key[0] + 'pow failed') return retVal except Exception as error: logger.error('Failed to merge keys.', error=error)