From fbd82d38fe0df0498cfa8b85b771f9dc074c289f Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Tue, 9 Oct 2018 18:36:52 -0500 Subject: [PATCH] work on foward secrecy --- onionr/core.py | 7 ++++--- onionr/onionrblockapi.py | 8 ++++---- onionr/onionrcrypto.py | 8 ++++++-- onionr/onionrusers.py | 28 +++++++++++++++++++--------- onionr/onionrutils.py | 3 ++- 5 files changed, 35 insertions(+), 19 deletions(-) diff --git a/onionr/core.py b/onionr/core.py index 7a1325cc..df0430c2 100644 --- a/onionr/core.py +++ b/onionr/core.py @@ -727,12 +727,13 @@ class Core: try: forwardEncrypted = onionrusers.OnionrUser(self, asymPeer).forwardEncrypt(data) data = forwardEncrypted[0] - meta['newFSKey'] = forwardEncrypted[1] meta['forwardEnc'] = True except onionrexceptions.InvalidPubkey: onionrusers.OnionrUser(self, asymPeer).generateForwardKey() - fsKey = onionrusers.OnionrUser(self, asymPeer).getGeneratedForwardKeys()[0] - meta['newFSKey'] = fsKey[0] + else: + logger.info(forwardEncrypted) + fsKey = onionrusers.OnionrUser(self, asymPeer).getGeneratedForwardKeys()[0] + meta['newFSKey'] = fsKey[0] jsonMeta = json.dumps(meta) if sign: signature = self._crypto.edSign(jsonMeta.encode() + data, key=self._crypto.privKey, encodeResult=True) diff --git a/onionr/onionrblockapi.py b/onionr/onionrblockapi.py index f7d66891..dbc05a0a 100644 --- a/onionr/onionrblockapi.py +++ b/onionr/onionrblockapi.py @@ -97,12 +97,12 @@ class Block: pass else: try: - self.bcontent = onionrusers.OnionrUser(self.core, self.signer).forwardDecrypt(self.bcontent) - except onionrexceptions.DecryptionError: + self.bcontent = onionrusers.OnionrUser(self.getCore(), self.signer).forwardDecrypt(self.bcontent) + except (onionrexceptions.DecryptionError, nacl.exceptions.CryptoError) as e: + logger.error(str(e)) pass except nacl.exceptions.CryptoError: - pass - #logger.debug('Could not decrypt block. Either invalid key or corrupted data') + logger.debug('Could not decrypt block. Either invalid key or corrupted data') else: retData = True self.decrypted = True diff --git a/onionr/onionrcrypto.py b/onionr/onionrcrypto.py index ab07edd2..8285f74d 100644 --- a/onionr/onionrcrypto.py +++ b/onionr/onionrcrypto.py @@ -142,7 +142,7 @@ class OnionrCrypto: retVal = anonBox.encrypt(data, encoder=encoding) return retVal - def pubKeyDecrypt(self, data, pubkey='', anonymous=False, encodedData=False): + def pubKeyDecrypt(self, data, pubkey='', privkey='', anonymous=False, encodedData=False): '''pubkey decrypt (Curve25519, taken from Ed25519 pubkey)''' retVal = False if encodedData: @@ -154,7 +154,11 @@ class OnionrCrypto: ourBox = nacl.public.Box(ownKey, pubkey) decrypted = ourBox.decrypt(data, encoder=encoding) elif anonymous: - anonBox = nacl.public.SealedBox(ownKey) + if self._core._utils.validatePubKey(privkey): + privkey = nacl.signing.SigningKey(seed=privkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_private_key() + anonBox = nacl.public.SealedBox(privkey) + else: + anonBox = nacl.public.SealedBox(ownKey) decrypted = anonBox.decrypt(data, encoder=encoding) return decrypted diff --git a/onionr/onionrusers.py b/onionr/onionrusers.py index e1a3c88b..7a3f515c 100644 --- a/onionr/onionrusers.py +++ b/onionr/onionrusers.py @@ -18,6 +18,7 @@ along with this program. If not, see . ''' import onionrblockapi, logger, onionrexceptions, json, sqlite3 +import nacl.exceptions class OnionrUser: def __init__(self, coreInst, publicKey): self.trust = 0 @@ -61,15 +62,20 @@ class OnionrUser: retData = self._core._crypto.pubKeyEncrypt(data, forwardKey, encodedData=True, anonymous=True) else: raise onionrexceptions.InvalidPubkey("No valid forward key available for this user") - self.generateForwardKey() + #self.generateForwardKey() return (retData, forwardKey) def forwardDecrypt(self, encrypted): retData = "" + logger.error(self.publicKey) + logger.error(self.getGeneratedForwardKeys()) for key in self.getGeneratedForwardKeys(): - retData = self._core._crypto.pubKeyDecrypt(encrypted, pubkey=key[1], anonymous=True) - logger('decrypting ' + key + ' got ' + retData) - if retData != False: + logger.info(encrypted) + try: + retData = self._core._crypto.pubKeyDecrypt(encrypted, privkey=key[1], anonymous=True, encodedData=True) + except nacl.exceptions.CryptoError: + retData = False + else: break else: raise onionrexceptions.DecryptionError("Could not decrypt forward secrecy content") @@ -110,8 +116,8 @@ class OnionrUser: # Prepare the insert time = self._core._utils.getEpoch() newKeys = self._core._crypto.generatePubKey() - newPub = newKeys[0] - newPriv = newKeys[1] + newPub = self._core._utils.bytesToStr(newKeys[0]) + newPriv = self._core._utils.bytesToStr(newKeys[1]) time = self._core._utils.getEpoch() command = (self.publicKey, newPub, newPriv, time, expire) @@ -126,14 +132,18 @@ class OnionrUser: # Fetch the keys we generated for the peer, that are still around conn = sqlite3.connect(self._core.forwardKeysFile, timeout=10) c = conn.cursor() - command = (self.publicKey,) + pubkey = self.publicKey + pubkey = self._core._utils.bytesToStr(pubkey) + command = (pubkey,) keyList = [] # list of tuples containing pub, private for peer for result in c.execute("SELECT * FROM myForwardKeys where peer=?", command): keyList.append((result[1], result[2])) - return keyList + if len(keyList) == 0: + self.generateForwardKey() + keyList = self.getGeneratedForwardKeys() + return list(keyList) def addForwardKey(self, newKey, expire=432000): - logger.info(newKey) if not self._core._utils.validatePubKey(newKey): raise onionrexceptions.InvalidPubkey # Add a forward secrecy key for the peer diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py index f4a06776..a17d27bc 100644 --- a/onionr/onionrutils.py +++ b/onionr/onionrutils.py @@ -262,7 +262,7 @@ class OnionrUtils: ''' myBlock = Block(blockHash, self._core) if myBlock.isEncrypted: - myBlock.decrypt() + logger.warn(myBlock.decrypt()) if (myBlock.isEncrypted and myBlock.decrypted) or (not myBlock.isEncrypted): blockType = myBlock.getMetadata('type') # we would use myBlock.getType() here, but it is bugged with encrypted blocks signer = self.bytesToStr(myBlock.signer) @@ -287,6 +287,7 @@ class OnionrUtils: else: self._core.updateBlockInfo(blockHash, 'expire', expireTime) else: + logger.info(myBlock.isEncrypted) logger.debug('Not processing metadata on encrypted block we cannot decrypt.') def escapeAnsi(self, line):