From c9b7528db43f1f07a80fe72c60c02f9d6ac82b6b Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Thu, 26 Apr 2018 14:56:17 -0500 Subject: [PATCH] more work on block headers, PMs now signed/verified --- onionr/core.py | 6 ++--- onionr/onionr.py | 2 +- onionr/onionrcrypto.py | 28 ++++++++++++++------ onionr/onionrutils.py | 59 +++++++++++++++++++++++++++++++++--------- 4 files changed, 71 insertions(+), 24 deletions(-) diff --git a/onionr/core.py b/onionr/core.py index f293eacb..fc9065e8 100644 --- a/onionr/core.py +++ b/onionr/core.py @@ -269,8 +269,8 @@ class Core: selfInsert = 1 else: selfInsert = 0 - data = (newHash, currentTime, 0, '', 0, selfInsert) - c.execute('INSERT INTO hashes VALUES(?, ?, ?, ?, ?, ?);', data) + data = (newHash, currentTime, '', selfInsert) + c.execute('INSERT INTO hashes (hash, dateReceived, dataType, dataSaved) VALUES(?, ?, ?, ?);', data) conn.commit() conn.close() @@ -618,7 +618,7 @@ class Core: retData = '' metadata = {'type': header} if sign: - signature = self._crypto.edSign(data, self._crypto.privKey, encodedResult=True) + signature = self._crypto.edSign(data, self._crypto.privKey, encodeResult=True) ourID = self._crypto.pubKeyHashID() metadata['id'] = ourID metadata['sig'] = signature diff --git a/onionr/onionr.py b/onionr/onionr.py index a92f2ec6..af1042c3 100755 --- a/onionr/onionr.py +++ b/onionr/onionr.py @@ -372,7 +372,7 @@ class Onionr: while True: messageToAdd = logger.readline('Broadcast message to network: ') - if len(messageToAdd) - 5 >= 1: + if len(messageToAdd) >= 1: break #addedHash = self.onionrCore.setData(messageToAdd) diff --git a/onionr/onionrcrypto.py b/onionr/onionrcrypto.py index 8f212f0e..c6fc0089 100644 --- a/onionr/onionrcrypto.py +++ b/onionr/onionrcrypto.py @@ -42,24 +42,36 @@ class OnionrCrypto: keyfile.write(self.pubKey + ',' + self.privKey) return - def edVerify(self, data, key): + def edVerify(self, data, key, sig, encodedData=True): '''Verify signed data (combined in nacl) to an ed25519 key''' key = nacl.signing.VerifyKey(key=key, encoder=nacl.encoding.Base32Encoder) - retData = '' - if encodeResult: - retData = key.verify(data.encode(), encoder=nacl.encoding.Base64Encoder) # .encode() is not the same as nacl.encoding + retData = False + sig = base64.b64decode(sig) + data = data.encode() + if encodedData: + try: + retData = key.verify(data, sig) # .encode() is not the same as nacl.encoding + except nacl.exceptions.BadSignatureError: + pass else: - retData = key.verify(data.encode()) + try: + retData = key.verify(data, sig) + except nacl.exceptions.BadSignatureError: + pass return retData def edSign(self, data, key, encodeResult=False): '''Ed25519 sign data''' + try: + data = data.encode() + except AttributeError: + pass key = nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder) retData = '' if encodeResult: - retData = key.sign(data.encode(), encoder=nacl.encoding.Base64Encoder) # .encode() is not the same as nacl.encoding + retData = key.sign(data, encoder=nacl.encoding.Base64Encoder).signature.decode() # .encode() is not the same as nacl.encoding else: - retData = key.sign(data.encode()) + retData = key.sign(data).signature return retData def pubKeyEncrypt(self, data, pubkey, anonymous=False, encodedData=False): @@ -72,7 +84,7 @@ class OnionrCrypto: encoding = nacl.encoding.RawEncoder if self.privKey != None and not anonymous: - ownKey = nacl.signing.SigningKey(seed=self.privKey, encoder=nacl.encoding.Base32Encoder()) + ownKey = nacl.signing.SigningKey(seed=self.privKey, encoder=nacl.encoding.Base32Encoder) key = nacl.signing.VerifyKey(key=pubkey, encoder=nacl.encoding.Base32Encoder).to_curve25519_public_key() ourBox = nacl.public.Box(ownKey, key) retVal = ourBox.encrypt(data.encode(), encoder=encoding) diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py index c5159525..59d65029 100644 --- a/onionr/onionrutils.py +++ b/onionr/onionrutils.py @@ -18,7 +18,7 @@ along with this program. If not, see . ''' # Misc functions that do not fit in the main api, but are useful -import getpass, sys, requests, os, socket, hashlib, logger, sqlite3, config, binascii, time, base64 +import getpass, sys, requests, os, socket, hashlib, logger, sqlite3, config, binascii, time, base64, json import nacl.signing, nacl.encoding if sys.version_info < (3, 6): @@ -55,7 +55,7 @@ class OnionrUtils: try: encrypted = self._core._crypto.pubKeyEncrypt(message, pubkey, anonymous=True, encodedData=True).decode() - block = self._core.insertBlock(encrypted, header='pm') + block = self._core.insertBlock(encrypted, header='pm', sign=True) if block == '': logger.error('Could not send PM') @@ -316,7 +316,8 @@ class OnionrUtils: ''' Find, decrypt, and return array of PMs (array of dictionary, {from, text}) ''' - blocks = self._core.getBlockList().split('\n') + #blocks = self._core.getBlockList().split('\n') + blocks = self._core.getBlocksByType('pm') message = '' sender = '' for i in blocks: @@ -324,15 +325,37 @@ class OnionrUtils: continue try: with open('data/blocks/' + i + '.dat', 'r') as potentialMessage: - message = potentialMessage.read() - if message.startswith('-pm-'): - try: - message = self._core._crypto.pubKeyDecrypt(message.replace('-pm-', ''), encodedData=True, anonymous=True) - except nacl.exceptions.CryptoError as e: - logger.error('Unable to decrypt ' + i, error=e) - pass + data = potentialMessage.read().split('}') + message = data[1] + sigResult = '' + signer = '' + + try: + metadata = json.loads(data[0] + '}') + except json.decoder.JSONDecodeError: + metadata = {} + try: + sig = json.loads(data[0].strip() + '}')['sig'] + signer = self._core._utils.getPeerByHashId(metadata['id']) + print('signer',signer) + print('signature', metadata['sig']) + except KeyError: + pass + else: + sigResult = self._core._crypto.edVerify(message, signer, sig, encodedData=True) + #sigResult = False + if sigResult != False: + sigResult = 'Valid signature by ' + signer else: - logger.info('Recieved message: ' + message.decode()) + sigResult = 'Invalid signature by ' + signer + + try: + message = self._core._crypto.pubKeyDecrypt(message, encodedData=True, anonymous=True) + except nacl.exceptions.CryptoError as e: + logger.error('Unable to decrypt ' + i, error=e) + else: + logger.info('Recieved message: ' + message.decode()) + logger.info(sigResult) except FileNotFoundError: pass except Exception as error: @@ -342,4 +365,16 @@ class OnionrUtils: def getPeerByHashId(self, hash): ''' Return the pubkey of the user if known from the hash - ''' \ No newline at end of file + ''' + if self._core._crypto.pubKeyHashID() == hash: + retData = self._core._crypto.pubKey + return retData + conn = sqlite3.connect(self._core.peerDB) + c = conn.cursor() + command = (hash,) + retData = '' + print('finding', hash) + for row in c.execute('SELECT ID FROM peers where hashID=?', command): + if row[0] != '': + retData = row[0] + return retData \ No newline at end of file