diff --git a/onionr/communicator2.py b/onionr/communicator2.py index 67a61e19..ccddc1cf 100755 --- a/onionr/communicator2.py +++ b/onionr/communicator2.py @@ -28,7 +28,7 @@ class OnionrCommunicatorDaemon: logger.warn('New (unstable) communicator is being used.') self.timers = [] - self._core = core.Core() + self._core = core.Core(torPort=sys.argv[2]) self.nistSaltTimestamp = 0 self.powSalt = 0 self.delay = 1 diff --git a/onionr/core.py b/onionr/core.py index 0d9aafde..9f10d762 100644 --- a/onionr/core.py +++ b/onionr/core.py @@ -20,7 +20,7 @@ import sqlite3, os, sys, time, math, base64, tarfile, getpass, simplecrypt, hashlib, nacl, logger, json, netcontroller, math, config from onionrblockapi import Block -import onionrutils, onionrcrypto, onionrproofs, onionrevents as events +import onionrutils, onionrcrypto, onionrproofs, onionrevents as events, onionrexceptions, onionrvalues if sys.version_info < (3, 6): try: @@ -30,7 +30,7 @@ if sys.version_info < (3, 6): sys.exit(1) class Core: - def __init__(self): + def __init__(self, torPort=0): ''' Initialize Core Onionr library ''' @@ -44,6 +44,7 @@ class Core: self.bootstrapFileLocation = 'static-data/bootstrap-nodes.txt' self.bootstrapList = [] + self.requirements = onionrvalues.OnionrValues() if not os.path.exists('data/'): os.mkdir('data/') @@ -659,11 +660,49 @@ class Core: conn.close() return True - def insertBlock(self, data, header='txt', sign=False, metadata = {}): + def insertBlock(self, data, header='txt', sign=False, encryptType='', symKey='', asymPeer='', meta = {}): ''' Inserts a block into the network + encryptType must be specified to encrypt a block ''' + try: + data.decode() + except AttributeError: + data = data.encode() + + retData = '' + signature = '' + signer = '' + + # only use header if not set in provided meta + try: + meta['type'] + except KeyError: + meta['type'] = header # block type + + jsonMeta = json.dumps(meta) + + if encryptType in ('asym', 'sym'): + metadata['encryptType'] = encryptType + else: + raise onionrexceptions.InvalidMetadata('encryptType must be asym or sym') + + # sign before encrypt, as unauthenticated crypto should not be a problem here + if sign: + signature = self._crypto.edSign(jsonMeta + data, key=self._crypto.privKey, encodeResult=True) + signer = self._crypto.pubKeyHashID() + + if len(jsonMeta) > 1000: + raise onionrexceptions.InvalidMetadata('meta in json encoded form must not exceed 1000 bytes') + + if encryptType == 'sym': + if len(symKey) < self.requirements.passwordLength: + raise onionrexceptions.SecurityError('Weak encryption key') + jsonMeta = self._crypto.symmetricEncrypt(jsonMeta, key=symKey, returnEncoded=True) + + metadata['meta'] = jsonMeta + powProof = onionrproofs.POW(data) powToken = '' # wait for proof to complete @@ -685,41 +724,7 @@ class Core: powProof.shutdown() return '' - try: - data.decode() - except AttributeError: - data = data.encode() - retData = '' - - metadata['type'] = header - metadata['powRandomToken'] = powToken - - sig = {} - - metadata = json.dumps(metadata) - metadata = metadata.encode() - signature = '' - - if sign: - signature = self._crypto.edSign(metadata + b'\n' + data, self._crypto.privKey, encodeResult=True) - ourID = self._crypto.pubKeyHashID() - # Convert from bytes on some py versions? - try: - ourID = ourID.decode() - except AttributeError: - pass - metadata = {'sig': signature, 'meta': metadata.decode()} - metadata = json.dumps(metadata) - metadata = metadata.encode() - - if len(data) == 0: - logger.error('Will not insert empty block') - else: - addedHash = self.setData(metadata + b'\n' + data) - self.addToBlockDB(addedHash, selfInsert=True) - self.setBlockType(addedHash, header) - retData = addedHash return retData def introduceNode(self): diff --git a/onionr/onionrexceptions.py b/onionr/onionrexceptions.py index 43077e67..aa00e65d 100644 --- a/onionr/onionrexceptions.py +++ b/onionr/onionrexceptions.py @@ -26,6 +26,10 @@ class Unknown(Exception): class Invalid(Exception): pass +# block exceptions +class InvalidMetadata(Exception): + pass + # network level exceptions class MissingPort(Exception): pass diff --git a/onionr/onionrvalues.py b/onionr/onionrvalues.py new file mode 100644 index 00000000..b9fd4a2b --- /dev/null +++ b/onionr/onionrvalues.py @@ -0,0 +1,24 @@ +''' + Onionr - P2P Microblogging Platform & Social network + + This file defines values and requirements used by Onionr +''' +''' + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +''' + +class OnionrValues: + def __init__(self): + self.passwordLength = 20 + self.blockMetadataLengths = {'meta': 1000, 'sig': 88, 'signer': 64, 'time': 10, 'powRandomToken': '1000'} \ No newline at end of file