From 40255538da9d34bae35c30a92097f2186aa94236 Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Fri, 13 Jul 2018 16:02:41 -0500 Subject: [PATCH] reworking PM system before migration to plugin and updating blockapi to encryption format --- onionr/communicator2.py | 11 +++++++++-- onionr/core.py | 14 +++++++------- onionr/onionrblockapi.py | 7 ++++++- onionr/onionrcrypto.py | 11 ++++++++++- onionr/onionrutils.py | 19 ++++++++++++------- 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/onionr/communicator2.py b/onionr/communicator2.py index 76359e42..450647ad 100755 --- a/onionr/communicator2.py +++ b/onionr/communicator2.py @@ -25,7 +25,6 @@ from defusedxml import minidom class OnionrCommunicatorDaemon: def __init__(self, debug, developmentMode): - logger.warn('New (unstable) communicator is being used.') # list of timer instances self.timers = [] @@ -57,6 +56,9 @@ class OnionrCommunicatorDaemon: # list of new blocks to download, added to when new block lists are fetched from peers self.blockQueue = [] + # list of blocks currently downloading, avoid s + self.currentDownloading = [] + # Clear the daemon queue for any dead messages if os.path.exists(self._core.queueDB): self._core.clearDaemonQueue() @@ -154,6 +156,10 @@ class OnionrCommunicatorDaemon: def getBlocks(self): '''download new blocks in queue''' for blockHash in self.blockQueue: + if blockHash in self.currentDownloading: + logger.debug('ALREADY DOWNLOADING ' + blockHash) + continue + self.currentDownloading.append(blockHash) logger.info("Attempting to download %s..." % blockHash) content = self.peerAction(self.pickOnlinePeer(), 'getData', data=blockHash) # block content from random peer (includes metadata) if content != False: @@ -171,7 +177,7 @@ class OnionrCommunicatorDaemon: content = content.decode() # decode here because sha3Hash needs bytes above metas = self._core._utils.getBlockMetadataFromData(content) # returns tuple(metadata, meta), meta is also in metadata metadata = metas[0] - meta = metas[1] + #meta = metas[1] if self._core._utils.validateMetadata(metadata): # check if metadata is valid if self._core._crypto.verifyPow(content): # check if POW is enough/correct logger.info('Block passed proof, saving.') @@ -191,6 +197,7 @@ class OnionrCommunicatorDaemon: pass logger.warn('Block hash validation failed for ' + blockHash + ' got ' + tempHash) self.blockQueue.remove(blockHash) # remove from block queue both if success or false + self.currentDownloading.remove(blockHash) self.decrementThreadCount('getBlocks') return diff --git a/onionr/core.py b/onionr/core.py index e1dce148..535c6b0a 100644 --- a/onionr/core.py +++ b/onionr/core.py @@ -727,15 +727,15 @@ class Core: if encryptType == 'sym': if len(symKey) < self.requirements.passwordLength: raise onionrexceptions.SecurityError('Weak encryption key') - jsonMeta = self._crypto.symmetricEncrypt(jsonMeta, key=symKey, returnEncoded=True) - data = self._crypto.symmetricEncrypt(data, key=symKey, returnEncoded=True) - signature = self._crypto.symmetricEncrypt(signature, key=symKey, returnEncoded=True) - signer = self._crypto.symmetricEncrypt(signer, key=symKey, returnEncoded=True) + jsonMeta = self._crypto.symmetricEncrypt(jsonMeta, key=symKey, returnEncoded=True).decode() + data = self._crypto.symmetricEncrypt(data, key=symKey, returnEncoded=True).decode() + signature = self._crypto.symmetricEncrypt(signature, key=symKey, returnEncoded=True).decode() + signer = self._crypto.symmetricEncrypt(signer, key=symKey, returnEncoded=True).decode() elif encryptType == 'asym': if self._utils.validatePubKey(asymPeer): - jsonMeta = self._crypto.pubKeyEncrypt(jsonMeta, asymPeer, encodedData=True) - data = self._crypto.pubKeyEncrypt(data, asymPeer, encodedData=True) - signature = self._crypto.pubKeyEncrypt(signature, asymPeer, encodedData=True) + jsonMeta = self._crypto.pubKeyEncrypt(jsonMeta, asymPeer, encodedData=True).decode() + data = self._crypto.pubKeyEncrypt(data, asymPeer, encodedData=True).decode() + signature = self._crypto.pubKeyEncrypt(signature, asymPeer, encodedData=True).decode() else: raise onionrexceptions.InvalidPubkey(asymPeer + ' is not a valid base32 encoded ed25519 key') diff --git a/onionr/onionrblockapi.py b/onionr/onionrblockapi.py index dbb358af..56be7617 100644 --- a/onionr/onionrblockapi.py +++ b/onionr/onionrblockapi.py @@ -51,6 +51,7 @@ class Block: self.parent = None self.bheader = {} self.bmetadata = {} + self.isEncrypted = False # handle arguments if self.getCore() is None: @@ -118,7 +119,11 @@ class Block: self.raw = str(blockdata) self.bheader = json.loads(self.getRaw()[:self.getRaw().index('\n')]) self.bcontent = self.getRaw()[self.getRaw().index('\n') + 1:] - self.bmetadata = json.loads(self.getHeader('meta', None)) + if self.bheader['encryptType'] in ('asym', 'sym'): + self.bmetadata = self.getHeader('meta', None) + self.isEncrypted = True + else: + self.bmetadata = json.loads(self.getHeader('meta', None)) self.parent = self.getMetadata('parent', None) self.btype = self.getMetadata('type', None) self.powHash = self.getMetadata('powHash', None) diff --git a/onionr/onionrcrypto.py b/onionr/onionrcrypto.py index 1500cea1..40dca90f 100644 --- a/onionr/onionrcrypto.py +++ b/onionr/onionrcrypto.py @@ -114,6 +114,11 @@ class OnionrCrypto: '''Encrypt to a public key (Curve25519, taken from base32 Ed25519 pubkey)''' retVal = '' + try: + pubkey = pubkey.encode() + except AttributeError: + pass + if encodedData: encoding = nacl.encoding.Base64Encoder else: @@ -127,7 +132,11 @@ class OnionrCrypto: elif anonymous: key = nacl.signing.VerifyKey(key=pubkey, encoder=nacl.encoding.Base32Encoder).to_curve25519_public_key() anonBox = nacl.public.SealedBox(key) - retVal = anonBox.encrypt(data.encode(), encoder=encoding) + try: + data = data.encode() + except AttributeError: + pass + retVal = anonBox.encrypt(data, encoder=encoding) return retVal def pubKeyDecrypt(self, data, pubkey='', anonymous=False, encodedData=False): diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py index 077fe302..dc1c1e49 100644 --- a/onionr/onionrutils.py +++ b/onionr/onionrutils.py @@ -59,7 +59,7 @@ class OnionrUtils: High level function to encrypt a message to a peer and insert it as a block ''' - self._core.insertBlock(message, header='pm', sign=True, encryptType='sym', symKey=pubkey) + self._core.insertBlock(message, header='pm', sign=True, encryptType='asym', asymPeer=pubkey) return @@ -117,7 +117,7 @@ class OnionrUtils: else: logger.warn("Failed to add key") else: - logger.warn('%s pow failed' % key[0]) + logger.debug('%s pow failed' % key[0]) return retVal except Exception as error: logger.error('Failed to merge keys.', error=error) @@ -204,18 +204,23 @@ class OnionrUtils: def getBlockMetadataFromData(self, blockData): ''' - accepts block contents as string and returns a tuple of metadata, meta (meta being internal metadata) + accepts block contents as string, returns a tuple of metadata, meta (meta being internal metadata, which will be returned as an encrypted base64 string if it is encrypted, dict if not). + ''' + meta = {} try: blockData = blockData.encode() except AttributeError: pass metadata = json.loads(blockData[:blockData.find(b'\n')].decode()) data = blockData[blockData.find(b'\n'):].decode() - try: - meta = json.loads(metadata['meta']) - except KeyError: - meta = {} + + if not metadata['encryptType'] in ('asym', 'sym'): + try: + meta = json.loads(metadata['meta']) + except KeyError: + pass + meta = metadata['meta'] return (metadata, meta, data) def checkPort(self, port, host=''):