From 586e9230cd61b3985c5bc60320eac87a98b51e9f Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Tue, 20 Feb 2018 20:44:56 -0600 Subject: [PATCH] fixed message spam, rewrote draft, work on crypto --- docs/onionr-draft.md | 2 ++ onionr/api.py | 8 ++++---- onionr/communicator.py | 3 ++- onionr/core.py | 3 ++- onionr/netcontroller.py | 9 +++++++-- onionr/onionr.py | 4 +++- onionr/onionrcrypto.py | 42 +++++++++++++++++++++++++++++++++++------ reset.sh | 5 +++++ 8 files changed, 61 insertions(+), 15 deletions(-) create mode 100755 reset.sh diff --git a/docs/onionr-draft.md b/docs/onionr-draft.md index 6fb79cbe..5ab91cb0 100644 --- a/docs/onionr-draft.md +++ b/docs/onionr-draft.md @@ -24,6 +24,8 @@ All traffic is over Tor/I2P, connecting only to Tor onion and I2P hidden service Onionr nodes use HTTP (over Tor/I2P) to exchange keys, metadata, and blocks. Blocks are identified by their sha3_256 hash. Nodes sync a table of blocks hashes and attempt to download blocks they do not yet have from random peers. +Blocks may be encrypted using Curve25519. + ## Connections When a node first comes online, it attempts to bootstrap using a default list provided by a client. diff --git a/onionr/api.py b/onionr/api.py index 73c65b48..666b7783 100755 --- a/onionr/api.py +++ b/onionr/api.py @@ -47,7 +47,7 @@ class API: if os.path.exists('dev-enabled'): self._developmentMode = True logger.set_level(logger.LEVEL_DEBUG) - logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)') + #logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)') else: self._developmentMode = False logger.set_level(logger.LEVEL_INFO) @@ -172,9 +172,9 @@ class API: resp = Response("Invalid request") return resp - - logger.info('Starting client on ' + self.host + ':' + str(bindPort) + '...') - logger.debug('Client token: ' + logger.colors.underline + self.clientToken) + if not os.environ.get("WERKZEUG_RUN_MAIN") == "true": + logger.info('Starting client on ' + self.host + ':' + str(bindPort) + '...') + logger.debug('Client token: ' + logger.colors.underline + self.clientToken) app.run(host=self.host, port=bindPort, debug=True, threaded=True) diff --git a/onionr/communicator.py b/onionr/communicator.py index 7fe5ecd1..4b6e49a8 100755 --- a/onionr/communicator.py +++ b/onionr/communicator.py @@ -20,7 +20,7 @@ and code to operate as a daemon, getting commands from the command queue databas along with this program. If not, see . ''' import sqlite3, requests, hmac, hashlib, time, sys, os, math, logger, urllib.parse -import core, onionrutils +import core, onionrutils, onionrcrypto class OnionrCommunicate: def __init__(self, debug, developmentMode): @@ -31,6 +31,7 @@ class OnionrCommunicate: ''' self._core = core.Core() self._utils = onionrutils.OnionrUtils(self._core) + self._crypto = onionrcrypto.OnionrCrypto(self._core) blockProcessTimer = 0 blockProcessAmount = 5 heartBeatTimer = 0 diff --git a/onionr/core.py b/onionr/core.py index d1a03b31..29d84a55 100644 --- a/onionr/core.py +++ b/onionr/core.py @@ -41,13 +41,14 @@ class Core: self.blockDB = 'data/blocks.db' self.blockDataLocation = 'data/blocks/' self._utils = onionrutils.OnionrUtils(self) + + # Initialize the crypto object self._crypto = onionrcrypto.OnionrCrypto(self) if not os.path.exists('data/'): os.mkdir('data/') if not os.path.exists('data/blocks/'): os.mkdir('data/blocks/') - if not os.path.exists(self.blockDB): self.createBlockDB() diff --git a/onionr/netcontroller.py b/onionr/netcontroller.py index dcb3c3a5..058d8e4a 100644 --- a/onionr/netcontroller.py +++ b/onionr/netcontroller.py @@ -103,7 +103,12 @@ HiddenServicePort 80 127.0.0.1:''' + str(self.hsPort) + ''' int(pidN) except: return - os.kill(int(pidN), signal.SIGTERM) - os.remove('data/torPid.txt') + try: + os.kill(int(pidN), signal.SIGTERM) + os.remove('data/torPid.txt') + except ProcessLookupError: + pass + except FileNotFoundError: + pass return diff --git a/onionr/onionr.py b/onionr/onionr.py index 87b02442..d3c51a4f 100755 --- a/onionr/onionr.py +++ b/onionr/onionr.py @@ -47,7 +47,6 @@ class Onionr: if os.path.exists('dev-enabled'): self._developmentMode = True logger.set_level(logger.LEVEL_DEBUG) - logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)') else: self._developmentMode = False logger.set_level(logger.LEVEL_INFO) @@ -211,11 +210,14 @@ class Onionr: def daemon(self): ''' Start the Onionr communication daemon ''' if not os.environ.get("WERKZEUG_RUN_MAIN") == "true": + if self._developmentMode: + logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)') net = NetController(self.config['CLIENT']['PORT']) logger.info('Tor is starting...') if not net.startTor(): sys.exit(1) logger.info('Started Tor .onion service: ' + logger.colors.underline + net.myID) + logger.info('Our Public key: ' + self.onionrCore._crypto.pubKey) time.sleep(1) subprocess.Popen(["./communicator.py", "run", str(net.socksPort)]) logger.debug('Started communicator') diff --git a/onionr/onionrcrypto.py b/onionr/onionrcrypto.py index e9f89c7c..6b282341 100644 --- a/onionr/onionrcrypto.py +++ b/onionr/onionrcrypto.py @@ -17,21 +17,51 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' -import nacl +import nacl.signing, nacl.encoding, nacl.public, os class OnionrCrypto: def __init__(self, coreInstance): self._core = coreInstance + self._keyFile = 'data/keys.txt' + self.pubKey = None + self.privKey = None + + # Load our own pub/priv Ed25519 keys, gen & save them if they don't exist + if os.path.exists(self._keyFile): + with open('data/keys.txt', 'r') as keys: + keys = keys.read().split(',') + self.pubKey = keys[0] + self.privKey = keys[1] + 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) return - def symmetricPeerEncrypt(self, data, key): + def pubKeyEncrypt(self, data, peer): + '''Encrypt to a peers public key (Curve25519, taken from Ed25519 pubkey)''' return - def symmetricPeerDecrypt(self, data, key): + def pubKeyEncrypt(self, data, peer): + '''pubkey decrypt (Curve25519, taken from Ed25519 pubkey)''' + return + + def symmetricPeerEncrypt(self, data): + '''Salsa20 encrypt data to peer (with mac)''' + return + + def symmetricPeerDecrypt(self, data, peer): + '''Salsa20 decrypt data from peer (with mac)''' return - def generateSymmetric(): + def generateSymmetric(self, data, peer): + '''Generate symmetric key''' return - def generateHMAC(): - return \ No newline at end of file + def generatePubKey(self): + '''Generate a Ed25519 public key pair, return tuple of base64encoded pubkey, privkey''' + private_key = nacl.signing.SigningKey.generate() + public_key = private_key.verify_key.encode(encoder=nacl.encoding.Base32Encoder()) + return (public_key.decode(), private_key.encode(encoder=nacl.encoding.Base32Encoder()).decode()) \ No newline at end of file diff --git a/reset.sh b/reset.sh new file mode 100755 index 00000000..eaf6641b --- /dev/null +++ b/reset.sh @@ -0,0 +1,5 @@ +#!/bin/bash +echo "RESETING ONIONR" +rm onionr/data/blocks/*.dat +rm onionr/data/peers.db +rm onionr/data/blocks.db