progress in removing core

master
Kevin Froman 2019-07-25 11:14:13 -05:00
parent 3d50dbcaac
commit 19fa128710
14 changed files with 114 additions and 449 deletions

View File

@ -17,8 +17,9 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
''' '''
from coredb import dbfiles
import sqlite3, os import sqlite3, os
from coredb import dbfiles
import filepaths
def createAddressDB(): def createAddressDB():
''' '''
@ -116,6 +117,9 @@ def createBlockDB():
def createBlockDataDB(): def createBlockDataDB():
if os.path.exists(dbfiles.block_data_db): if os.path.exists(dbfiles.block_data_db):
raise FileExistsError("Block data database already exists") raise FileExistsError("Block data database already exists")
else:
if not os.path.exists(filepaths.block_data_location):
os.mkdir(filepaths.block_data_location)
conn = sqlite3.connect(dbfiles.block_data_db) conn = sqlite3.connect(dbfiles.block_data_db)
c = conn.cursor() c = conn.cursor()
c.execute('''CREATE TABLE blockData( c.execute('''CREATE TABLE blockData(

View File

@ -4,6 +4,7 @@ if not home.endswith('/'): home += '/'
usage_file = home + 'disk-usage.txt' usage_file = home + 'disk-usage.txt'
block_data_location = home + 'blocks/' block_data_location = home + 'blocks/'
contacts_location = home + 'contacts/'
public_API_host_file = home + 'public-host.txt' public_API_host_file = home + 'public-host.txt'
private_API_host_file = home + 'private-host.txt' private_API_host_file = home + 'private-host.txt'
bootstrap_file_location = 'static-data/bootstrap-nodes.txt' bootstrap_file_location = 'static-data/bootstrap-nodes.txt'

View File

@ -32,7 +32,7 @@ if sys.version_info[0] == 2 or sys.version_info[1] < MIN_PY_VERSION:
from utils import detectoptimization from utils import detectoptimization
if detectoptimization.detect_optimization(): if detectoptimization.detect_optimization():
sys.stderr.write('Error, Onionr cannot be run in optimized mode\n') sys.stderr.write('Error, Onionr cannot be run with an optimized Python interpreter\n')
sys.exit(1) sys.exit(1)
from utils import createdirs from utils import createdirs
createdirs.create_dirs() createdirs.create_dirs()

View File

@ -18,7 +18,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
''' '''
from . import generate, hashers, getourkeypair, signing, encryption from . import generate, hashers, getourkeypair, signing, encryption, cryptoutils
generate_deterministic = generate.generate_deterministic
generate = generate.generate_pub_key generate = generate.generate_pub_key
keypair = getourkeypair.get_keypair() keypair = getourkeypair.get_keypair()

View File

@ -1,6 +1,26 @@
import nacl.signing, nacl.encoding import nacl.signing, nacl.encoding, nacl.pwhash
import onionrexceptions
from onionrutils import bytesconverter
def generate_pub_key(): def generate_pub_key():
'''Generate a Ed25519 public key pair, return tuple of base32encoded pubkey, privkey''' '''Generate a Ed25519 public key pair, return tuple of base32encoded pubkey, privkey'''
private_key = nacl.signing.SigningKey.generate() private_key = nacl.signing.SigningKey.generate()
public_key = private_key.verify_key.encode(encoder=nacl.encoding.Base32Encoder()) public_key = private_key.verify_key.encode(encoder=nacl.encoding.Base32Encoder())
return (public_key.decode(), private_key.encode(encoder=nacl.encoding.Base32Encoder()).decode()) return (public_key.decode(), private_key.encode(encoder=nacl.encoding.Base32Encoder()).decode())
def generate_deterministic(passphrase, bypassCheck=False):
'''Generate a Ed25519 public key pair from a password'''
passStrength = 25
passphrase = bytesconverter.str_to_bytes(passphrase) # Convert to bytes if not already
# Validate passphrase length
if not bypassCheck:
if len(passphrase) < passStrength:
raise onionrexceptions.PasswordStrengthError("Passphase must be at least %s characters" % (passStrength,))
# KDF values
kdf = nacl.pwhash.argon2id.kdf
salt = b"U81Q7llrQcdTP0Ux" # Does not need to be unique or secret, but must be 16 bytes
ops = nacl.pwhash.argon2id.OPSLIMIT_SENSITIVE
mem = nacl.pwhash.argon2id.MEMLIMIT_SENSITIVE
key = kdf(32, passphrase, salt, opslimit=ops, memlimit=mem) # Generate seed for ed25519 key
key = nacl.signing.SigningKey(key)
return (key.verify_key.encode(nacl.encoding.Base32Encoder).decode(), key.encode(nacl.encoding.Base32Encoder).decode())

View File

@ -34,264 +34,6 @@ PLUGIN_VERSION = '0.0.1'
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
import sentboxdb, mailapi, loadinbox # import after path insert import sentboxdb, mailapi, loadinbox # import after path insert
flask_blueprint = mailapi.flask_blueprint flask_blueprint = mailapi.flask_blueprint
"""
def draw_border(text):
# This function taken from https://stackoverflow.com/a/20757491 by https://stackoverflow.com/users/816449/bunyk, under https://creativecommons.org/licenses/by-sa/3.0/
lines = text.splitlines()
width = max(len(s) for s in lines)
res = ['' + '' * width + '']
for s in lines:
res.append('' + (s + ' ' * width)[:width] + '')
res.append('' + '' * width + '')
return '\n'.join(res)
class MailStrings:
def __init__(self, mailInstance):
self.mailInstance = mailInstance
self.programTag = 'OnionrMail v%s' % (PLUGIN_VERSION)
choices = ['view inbox', 'view sentbox', 'send message', 'toggle pseudonymity', 'quit']
self.mainMenuChoices = choices
self.mainMenu = '''-----------------
1. %s
2. %s
3. %s
4. %s
5. %s''' % (choices[0], choices[1], choices[2], choices[3], choices[4])
class OnionrMail:
def __init__(self, pluginapi):
self.strings = MailStrings(self)
self.sentboxTools = sentboxdb.SentBox()
self.sentboxList = []
self.sentMessages = {}
self.doSigs = True
return
def inbox(self):
blockCount = 0
pmBlockMap = {}
pmBlocks = {}
logger.info('Decrypting messages...', terminal=True)
choice = ''
displayList = []
subject = ''
# this could use a lot of memory if someone has received a lot of messages
for blockHash in blockmetadb.get_blocks_by_type('pm'):
pmBlocks[blockHash] = Block(blockHash, core=self.myCore)
pmBlocks[blockHash].decrypt()
blockCount = 0
for blockHash in pmBlocks:
if not pmBlocks[blockHash].decrypted:
continue
blockCount += 1
pmBlockMap[blockCount] = blockHash
block = pmBlocks[blockHash]
senderKey = block.signer
try:
senderKey = senderKey.decode()
except AttributeError:
pass
senderDisplay = onionrusers.OnionrUser(self.myCore, senderKey).getName()
if senderDisplay == 'anonymous':
senderDisplay = senderKey
blockDate = pmBlocks[blockHash].getDate().strftime("%m/%d %H:%M")
try:
subject = pmBlocks[blockHash].bmetadata['subject']
except KeyError:
subject = ''
displayList.append('%s. %s - %s - <%s>: %s' % (blockCount, blockDate, senderDisplay[:12], subject[:10], blockHash))
while choice not in ('-q', 'q', 'quit'):
for i in displayList:
logger.info(i, terminal=True)
try:
choice = logger.readline('Enter a block number, -r to refresh, or -q to stop: ').strip().lower()
except (EOFError, KeyboardInterrupt):
choice = '-q'
if choice in ('-q', 'q', 'quit'):
continue
if choice in ('-r', 'r', 'refresh'):
# dirty hack
self.inbox()
return
try:
choice = int(choice)
except ValueError:
pass
else:
try:
pmBlockMap[choice]
readBlock = pmBlocks[pmBlockMap[choice]]
except KeyError:
pass
else:
cancel = ''
readBlock.verifySig()
senderDisplay = bytesconverter.bytes_to_str(readBlock.signer)
if len(senderDisplay.strip()) == 0:
senderDisplay = 'Anonymous'
logger.info('Message received from %s' % (senderDisplay,), terminal=True)
logger.info('Valid signature: %s' % readBlock.validSig, terminal=True)
if not readBlock.validSig:
logger.warn('This message has an INVALID/NO signature. ANYONE could have sent this message.', terminal=True)
cancel = logger.readline('Press enter to continue to message, or -q to not open the message (recommended).')
print('')
if cancel != '-q':
try:
print(draw_border(escapeansi.escape_ANSI(readBlock.bcontent.decode().strip())))
except ValueError:
logger.warn('Error presenting message. This is usually due to a malformed or blank message.', terminal=True)
pass
if readBlock.validSig:
reply = logger.readline("Press enter to continue, or enter %s to reply" % ("-r",))
print('')
if reply == "-r":
self.draft_message(bytesconverter.bytes_to_str(readBlock.signer,))
else:
logger.readline("Press enter to continue")
print('')
return
def sentbox(self):
'''
Display sent mail messages
'''
entering = True
while entering:
self.get_sent_list()
logger.info('Enter a block number or -q to return', terminal=True)
try:
choice = input('>')
except (EOFError, KeyboardInterrupt) as e:
entering = False
else:
try:
choice = int(choice) - 1
except ValueError:
pass
else:
try:
self.sentboxList[int(choice)]
except (IndexError, ValueError) as e:
logger.warn('Invalid block.', terminal=True)
else:
logger.info('Sent to: ' + self.sentMessages[self.sentboxList[int(choice)]][1], terminal=True)
# Print ansi escaped sent message
logger.info(escapeansi.escape_ANSI(self.sentMessages[self.sentboxList[int(choice)]][0]), terminal=True)
input('Press enter to continue...')
finally:
if choice == '-q':
entering = False
return
def get_sent_list(self, display=True):
count = 1
self.sentboxList = []
self.sentMessages = {}
for i in self.sentboxTools.listSent():
self.sentboxList.append(i['hash'])
self.sentMessages[i['hash']] = (bytesconverter.bytes_to_str(i['message']), i['peer'], i['subject'])
if display:
logger.info('%s. %s - %s - (%s) - %s' % (count, i['hash'], i['peer'][:12], i['subject'], i['date']), terminal=True)
count += 1
return json.dumps(self.sentMessages)
def draft_message(self, recip=''):
message = ''
newLine = ''
subject = ''
entering = False
if len(recip) == 0:
entering = True
while entering:
try:
recip = logger.readline('Enter peer address, or -q to stop:').strip()
if recip in ('-q', 'q'):
raise EOFError
if not stringvalidators.validate_pub_key(recip):
raise onionrexceptions.InvalidPubkey('Must be a valid ed25519 base32 encoded public key')
except onionrexceptions.InvalidPubkey:
logger.warn('Invalid public key', terminal=True)
except (KeyboardInterrupt, EOFError):
entering = False
else:
break
else:
# if -q or ctrl-c/d, exit function here, otherwise we successfully got the public key
return
try:
subject = logger.readline('Message subject: ')
except (KeyboardInterrupt, EOFError):
pass
cancelEnter = False
logger.info('Enter your message, stop by entering -q on a new line. -c to cancel', terminal=True)
while newLine != '-q':
try:
newLine = input()
except (KeyboardInterrupt, EOFError):
cancelEnter = True
if newLine == '-c':
cancelEnter = True
break
if newLine == '-q':
continue
newLine += '\n'
message += newLine
if not cancelEnter:
logger.info('Inserting encrypted message as Onionr block....', terminal=True)
blockID = self.myCore.insertBlock(message, header='pm', encryptType='asym', asymPeer=recip, sign=self.doSigs, meta={'subject': subject})
def toggle_signing(self):
self.doSigs = not self.doSigs
def menu(self):
choice = ''
while True:
sigMsg = 'Message Signing: %s'
logger.info(self.strings.programTag + '\n\nUser ID: ' + self.myCore._crypto.pubKey, terminal=True)
if self.doSigs:
sigMsg = sigMsg % ('enabled',)
else:
sigMsg = sigMsg % ('disabled (Your messages cannot be trusted)',)
if self.doSigs:
logger.info(sigMsg, terminal=True)
else:
logger.warn(sigMsg, terminal=True)
logger.info(self.strings.mainMenu.title(), terminal=True) # print out main menu
try:
choice = logger.readline('Enter 1-%s:\n' % (len(self.strings.mainMenuChoices))).lower().strip()
except (KeyboardInterrupt, EOFError):
choice = '5'
if choice in (self.strings.mainMenuChoices[0], '1'):
self.inbox()
elif choice in (self.strings.mainMenuChoices[1], '2'):
self.sentbox()
elif choice in (self.strings.mainMenuChoices[2], '3'):
self.draft_message()
elif choice in (self.strings.mainMenuChoices[3], '4'):
self.toggle_signing()
elif choice in (self.strings.mainMenuChoices[4], '5'):
logger.info('Goodbye.', terminal=True)
break
elif choice == '':
pass
else:
logger.warn('Invalid choice.', terminal=True)
return """
def add_deleted(keyStore, bHash): def add_deleted(keyStore, bHash):
existing = keyStore.get('deleted_mail') existing = keyStore.get('deleted_mail')

View File

@ -7,13 +7,12 @@ import nacl.signing, nacl.hash, nacl.encoding
TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/' TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/'
print("Test directory:", TEST_DIR) print("Test directory:", TEST_DIR)
os.environ["ONIONR_HOME"] = TEST_DIR os.environ["ONIONR_HOME"] = TEST_DIR
import core, onionr import onionrblocks
from utils import createdirs
c = core.Core() createdirs.create_dirs()
class OnionrBlockTests(unittest.TestCase): class OnionrBlockTests(unittest.TestCase):
def test_plaintext_insert(self): def test_plaintext_insert(self):
message = 'hello world' message = 'hello world'
c.insertBlock(message) onionrblocks.insert(message)
unittest.main() unittest.main()

View File

@ -6,35 +6,34 @@ TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/'
print("Test directory:", TEST_DIR) print("Test directory:", TEST_DIR)
os.environ["ONIONR_HOME"] = TEST_DIR os.environ["ONIONR_HOME"] = TEST_DIR
from urllib.request import pathname2url from urllib.request import pathname2url
import core, onionr from coredb import keydb
from utils import createdirs
c = core.Core() createdirs.create_dirs()
class OnionrTests(unittest.TestCase): class OnionrTests(unittest.TestCase):
def test_address_add(self): def test_address_add(self):
testAddresses = ['facebookcorewwwi.onion', '56kmnycrvepfarolhnx6t2dvmldfeyg7jdymwgjb7jjzg47u2lqw2sad.onion', '5bvb5ncnfr4dlsfriwczpzcvo65kn7fnnlnt2ln7qvhzna2xaldq.b32.i2p'] testAddresses = ['facebookcorewwwi.onion', '56kmnycrvepfarolhnx6t2dvmldfeyg7jdymwgjb7jjzg47u2lqw2sad.onion', '5bvb5ncnfr4dlsfriwczpzcvo65kn7fnnlnt2ln7qvhzna2xaldq.b32.i2p']
for address in testAddresses: for address in testAddresses:
c.addAddress(address) keydb.addkeys.add_address(address)
dbAddresses = c.listAdders() dbAddresses = keydb.listkeys.list_adders()
for address in testAddresses: for address in testAddresses:
self.assertIn(address, dbAddresses) self.assertIn(address, dbAddresses)
invalidAddresses = [None, '', ' ', '\t', '\n', ' test ', 24, 'fake.onion', 'fake.b32.i2p'] invalidAddresses = [None, '', ' ', '\t', '\n', ' test ', 24, 'fake.onion', 'fake.b32.i2p']
for address in invalidAddresses: for address in invalidAddresses:
try: try:
c.addAddress(address) keydb.addkeys.add_address(address)
except TypeError: except TypeError:
pass pass
dbAddresses = c.listAdders() dbAddresses = keydb.listkeys.list_adders()
for address in invalidAddresses: for address in invalidAddresses:
self.assertNotIn(address, dbAddresses) self.assertNotIn(address, dbAddresses)
def test_address_info(self): def test_address_info(self):
adder = 'nytimes3xbfgragh.onion' adder = 'nytimes3xbfgragh.onion'
c.addAddress(adder) keydb.addkeys.add_address(adder)
self.assertNotEqual(c.getAddressInfo(adder, 'success'), 1000) self.assertNotEqual(keydb.transportinfo.get_address_info(adder, 'success'), 1000)
c.setAddressInfo(adder, 'success', 1000) keydb.transportinfo.set_address_info(adder, 'success', 1000)
self.assertEqual(c.getAddressInfo(adder, 'success'), 1000) self.assertEqual(keydb.transportinfo.get_address_info(adder, 'success'), 1000)
unittest.main() unittest.main()

View File

@ -1,70 +0,0 @@
#!/usr/bin/env python3
import sys, os
sys.path.append(".")
import unittest, uuid, sqlite3
TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/'
print("Test directory:", TEST_DIR)
os.environ["ONIONR_HOME"] = TEST_DIR
from urllib.request import pathname2url
import core, onionr
core.Core()
class OnionrTests(unittest.TestCase):
def test_peer_db_creation(self):
try:
dburi = 'file:{}?mode=rw'.format(pathname2url(TEST_DIR + 'peers.db'))
conn = sqlite3.connect(dburi, uri=True, timeout=30)
cursor = conn.cursor()
conn.close()
except sqlite3.OperationalError:
self.assertTrue(False)
else:
self.assertTrue(True)
def test_block_db_creation(self):
try:
dburi = 'file:{}?mode=rw'.format(pathname2url(TEST_DIR + 'blocks.db'))
conn = sqlite3.connect(dburi, uri=True, timeout=30)
cursor = conn.cursor()
conn.close()
except sqlite3.OperationalError:
self.assertTrue(False)
else:
self.assertTrue(True)
def test_forward_keys_db_creation(self):
try:
dburi = 'file:{}?mode=rw'.format(pathname2url(TEST_DIR + 'forward-keys.db'))
conn = sqlite3.connect(dburi, uri=True, timeout=30)
cursor = conn.cursor()
conn.close()
except sqlite3.OperationalError:
self.assertTrue(False)
else:
self.assertTrue(True)
def test_address_db_creation(self):
try:
dburi = 'file:{}?mode=rw'.format(pathname2url(TEST_DIR + 'address.db'))
conn = sqlite3.connect(dburi, uri=True, timeout=30)
cursor = conn.cursor()
conn.close()
except sqlite3.OperationalError:
self.assertTrue(False)
else:
self.assertTrue(True)
def blacklist_db_creation(self):
try:
dburi = 'file:{}?mode=rw'.format(pathname2url(TEST_DIR + 'blacklist.db'))
conn = sqlite3.connect(dburi, uri=True, timeout=30)
cursor = conn.cursor()
conn.close()
except sqlite3.OperationalError:
self.assertTrue(False)
else:
self.assertTrue(True)
unittest.main()

View File

@ -4,11 +4,12 @@ sys.path.append(".")
import unittest, uuid import unittest, uuid
TEST_DIR_1 = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/' TEST_DIR_1 = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/'
TEST_DIR_2 = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/' TEST_DIR_2 = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/'
import core, onionr, time import onionr, time
import onionrexceptions import onionrexceptions, onionrcrypto as crypto
from onionrusers import onionrusers from onionrusers import onionrusers
from onionrusers import contactmanager from onionrusers import contactmanager
from utils import createdirs
class OnionrForwardSecrecyTests(unittest.TestCase): class OnionrForwardSecrecyTests(unittest.TestCase):
''' '''
@ -17,23 +18,23 @@ class OnionrForwardSecrecyTests(unittest.TestCase):
def test_forward_encrypt(self): def test_forward_encrypt(self):
os.environ["ONIONR_HOME"] = TEST_DIR_1 os.environ["ONIONR_HOME"] = TEST_DIR_1
o = onionr.Onionr() createdirs.create_dirs()
friend = o.onionrCore._crypto.generatePubKey() friend = crypto.generate()
friendUser = onionrusers.OnionrUser(o.onionrCore, friend[0], saveUser=True) friendUser = onionrusers.OnionrUser(friend[0], saveUser=True)
for x in range(5): for x in range(5):
message = 'hello world %s' % (random.randint(1, 1000)) message = 'hello world %s' % (random.randint(1, 1000))
forwardKey = friendUser.generateForwardKey() forwardKey = friendUser.generateForwardKey()
fakeForwardPair = o.onionrCore._crypto.generatePubKey() fakeForwardPair = crypto.generate()
self.assertTrue(friendUser.addForwardKey(fakeForwardPair[0])) self.assertTrue(friendUser.addForwardKey(fakeForwardPair[0]))
encrypted = friendUser.forwardEncrypt(message) encrypted = friendUser.forwardEncrypt(message)
decrypted = o.onionrCore._crypto.pubKeyDecrypt(encrypted[0], privkey=fakeForwardPair[1], encodedData=True) decrypted = crypto.encryption.pub_key_decrypt(encrypted[0], privkey=fakeForwardPair[1], encodedData=True)
self.assertEqual(decrypted, message.encode()) self.assertEqual(decrypted, message.encode())
return return

View File

@ -8,34 +8,32 @@ from onionrutils import stringvalidators, mnemonickeys
TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/' TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/'
print("Test directory:", TEST_DIR) print("Test directory:", TEST_DIR)
os.environ["ONIONR_HOME"] = TEST_DIR os.environ["ONIONR_HOME"] = TEST_DIR
import core, onionr, onionrexceptions import onionrcrypto as crypto, onionrexceptions
c = core.Core()
crypto = c._crypto
class OnionrCryptoTests(unittest.TestCase): class OnionrCryptoTests(unittest.TestCase):
def test_blake2b(self): def test_blake2b(self):
self.assertEqual(crypto.blake2bHash('test'), crypto.blake2bHash(b'test')) self.assertEqual(crypto.hashers.blake2b_hash('test'), crypto.hashers.blake2b_hash(b'test'))
self.assertEqual(crypto.blake2bHash(b'test'), crypto.blake2bHash(b'test')) self.assertEqual(crypto.hashers.blake2b_hash(b'test'), crypto.hashers.blake2b_hash(b'test'))
self.assertNotEqual(crypto.blake2bHash(''), crypto.blake2bHash(b'test')) self.assertNotEqual(crypto.hashers.blake2b_hash(''), crypto.hashers.blake2b_hash(b'test'))
try: try:
crypto.blake2bHash(None) crypto.hashers.blake2b_hash(None)
except nacl.exceptions.TypeError: except nacl.exceptions.TypeError:
pass pass
else: else:
self.assertTrue(False) self.assertTrue(False)
self.assertEqual(nacl.hash.blake2b(b'test'), crypto.blake2bHash(b'test')) self.assertEqual(nacl.hash.blake2b(b'test'), crypto.hashers.blake2b_hash(b'test'))
def test_sha3256(self): def test_sha3256(self):
hasher = hashlib.sha3_256() hasher = hashlib.sha3_256()
self.assertEqual(crypto.sha3Hash('test'), crypto.sha3Hash(b'test')) self.assertEqual(crypto.hashers.sha3_hash('test'), crypto.hashers.sha3_hash(b'test'))
self.assertEqual(crypto.sha3Hash(b'test'), crypto.sha3Hash(b'test')) self.assertEqual(crypto.hashers.sha3_hash(b'test'), crypto.hashers.sha3_hash(b'test'))
self.assertNotEqual(crypto.sha3Hash(''), crypto.sha3Hash(b'test')) self.assertNotEqual(crypto.hashers.sha3_hash(''), crypto.hashers.sha3_hash(b'test'))
try: try:
crypto.sha3Hash(None) crypto.hashers.sha3_hash(None)
except TypeError: except TypeError:
pass pass
else: else:
@ -43,21 +41,21 @@ class OnionrCryptoTests(unittest.TestCase):
hasher.update(b'test') hasher.update(b'test')
normal = hasher.hexdigest() normal = hasher.hexdigest()
self.assertEqual(crypto.sha3Hash(b'test'), normal) self.assertEqual(crypto.hashers.sha3_hash(b'test'), normal)
def valid_default_id(self): def valid_default_id(self):
self.assertTrue(stringvalidators.validate_pub_key(crypto.pubKey)) self.assertTrue(stringvalidators.validate_pub_key(crypto.pub_key))
def test_human_readable_length(self): def test_human_readable_length(self):
human = mnemonickeys.get_human_readable_ID(c) human = mnemonickeys.get_human_readable_ID()
self.assertTrue(len(human.split(' ')) == 32) self.assertTrue(len(human.split(' ')) == 32)
def test_safe_compare(self): def test_safe_compare(self):
self.assertTrue(crypto.safeCompare('test', 'test')) self.assertTrue(crypto.cryptoutils.safe_compare('test', 'test'))
self.assertTrue(crypto.safeCompare('test', b'test')) self.assertTrue(crypto.cryptoutils.safe_compare('test', b'test'))
self.assertFalse(crypto.safeCompare('test', 'test2')) self.assertFalse(crypto.cryptoutils.safe_compare('test', 'test2'))
try: try:
crypto.safeCompare('test', None) crypto.cryptoutils.safe_compare('test', None)
except TypeError: except TypeError:
pass pass
else: else:
@ -67,82 +65,53 @@ class OnionrCryptoTests(unittest.TestCase):
# Small chance that the randomized list will be same. Rerun test a couple times if it fails # Small chance that the randomized list will be same. Rerun test a couple times if it fails
startList = ['cat', 'dog', 'moose', 'rabbit', 'monkey', 'crab', 'human', 'dolphin', 'whale', 'etc'] * 10 startList = ['cat', 'dog', 'moose', 'rabbit', 'monkey', 'crab', 'human', 'dolphin', 'whale', 'etc'] * 10
self.assertNotEqual(startList, list(crypto.randomShuffle(startList))) self.assertNotEqual(startList, list(crypto.cryptoutils.random_shuffle(startList)))
self.assertTrue(len(list(crypto.randomShuffle(startList))) == len(startList)) self.assertTrue(len(list(crypto.cryptoutils.random_shuffle(startList))) == len(startList))
def test_asymmetric(self): def test_asymmetric(self):
keyPair = crypto.generatePubKey() keyPair = crypto.generate()
keyPair2 = crypto.generatePubKey() keyPair2 = crypto.generate()
message = "hello world" message = "hello world"
self.assertTrue(len(crypto.pubKeyEncrypt(message, keyPair2[0], encodedData=True)) > 0) self.assertTrue(len(crypto.encryption.pub_key_encrypt(message, keyPair2[0], encodedData=True)) > 0)
encrypted = crypto.pubKeyEncrypt(message, keyPair2[0], encodedData=False) encrypted = crypto.encryption.pub_key_encrypt(message, keyPair2[0], encodedData=False)
decrypted = crypto.pubKeyDecrypt(encrypted, privkey=keyPair2[1], encodedData=False) decrypted = crypto.encryption.pub_key_decrypt(encrypted, privkey=keyPair2[1], encodedData=False)
self.assertTrue(decrypted.decode() == message) self.assertTrue(decrypted.decode() == message)
try: try:
crypto.pubKeyEncrypt(None, keyPair2[0]) crypto.encryption.pub_key_encrypt(None, keyPair2[0])
except TypeError: except TypeError:
pass pass
else: else:
self.assertTrue(False) self.assertTrue(False)
blankMessage = crypto.pubKeyEncrypt('', keyPair2[0]) blankMessage = crypto.encryption.pub_key_encrypt('', keyPair2[0])
self.assertTrue('' == crypto.pubKeyDecrypt(blankMessage, privkey=keyPair2[1], encodedData=False).decode()) self.assertTrue('' == crypto.encryption.pub_key_decrypt(blankMessage, privkey=keyPair2[1], encodedData=False).decode())
# Try to encrypt arbitrary bytes # Try to encrypt arbitrary bytes
crypto.pubKeyEncrypt(os.urandom(32), keyPair2[0]) crypto.encryption.pub_key_encrypt(os.urandom(32), keyPair2[0])
def test_symmetric(self):
dataString = "this is a secret message"
dataBytes = dataString.encode()
key = b"tttttttttttttttttttttttttttttttt"
invalidKey = b'tttttttttttttttttttttttttttttttb'
encrypted = crypto.symmetricEncrypt(dataString, key, returnEncoded=True)
decrypted = crypto.symmetricDecrypt(encrypted, key, encodedMessage=True)
self.assertTrue(dataString == decrypted.decode())
try:
crypto.symmetricDecrypt(encrypted, invalidKey, encodedMessage=True)
except nacl.exceptions.CryptoError:
pass
else:
self.assertFalse(True)
try:
crypto.symmetricEncrypt(None, key, returnEncoded=True)
except AttributeError:
pass
else:
self.assertFalse(True)
crypto.symmetricEncrypt("string", key, returnEncoded=True)
try:
crypto.symmetricEncrypt("string", None, returnEncoded=True)
except nacl.exceptions.TypeError:
pass
else:
self.assertFalse(True)
def test_deterministic(self): def test_deterministic(self):
password = os.urandom(32) password = os.urandom(32)
gen = crypto.generateDeterministic(password) gen = crypto.generate_deterministic(password)
self.assertTrue(stringvalidators.validate_pub_key(gen[0])) self.assertTrue(stringvalidators.validate_pub_key(gen[0]))
try: try:
crypto.generateDeterministic('weakpassword') crypto.generate_deterministic('weakpassword')
except onionrexceptions.PasswordStrengthError: except onionrexceptions.PasswordStrengthError:
pass pass
else: else:
self.assertFalse(True) self.assertFalse(True)
try: try:
crypto.generateDeterministic(None) crypto.generate_deterministic(None)
except TypeError: except TypeError:
pass pass
else: else:
self.assertFalse(True) self.assertFalse(True)
gen = crypto.generateDeterministic('weakpassword', bypassCheck=True) gen = crypto.generate_deterministic('weakpassword', bypassCheck=True)
password = base64.b64encode(os.urandom(32)) password = base64.b64encode(os.urandom(32))
gen1 = crypto.generateDeterministic(password) gen1 = crypto.generate_deterministic(password)
gen2 = crypto.generateDeterministic(password) gen2 = crypto.generate_deterministic(password)
self.assertFalse(gen == gen1) self.assertFalse(gen == gen1)
self.assertTrue(gen1 == gen2) self.assertTrue(gen1 == gen2)
self.assertTrue(stringvalidators.validate_pub_key(gen1[0])) self.assertTrue(stringvalidators.validate_pub_key(gen1[0]))

View File

@ -6,37 +6,38 @@ import json
TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/' TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/'
print("Test directory:", TEST_DIR) print("Test directory:", TEST_DIR)
os.environ["ONIONR_HOME"] = TEST_DIR os.environ["ONIONR_HOME"] = TEST_DIR
import core, onionr
c = core.Core()
import onionrexceptions import onionrexceptions
from onionrusers import onionrusers from onionrusers import onionrusers
from onionrusers import contactmanager from onionrusers import contactmanager
import onionrcrypto as crypto
from coredb import keydb
from utils import identifyhome, createdirs
createdirs.create_dirs()
class OnionrUserTests(unittest.TestCase): class OnionrUserTests(unittest.TestCase):
''' '''
Tests both the onionrusers class and the contactmanager (which inherits it) Tests both the onionrusers class and the contactmanager (which inherits it)
''' '''
def test_users(self): def test_users(self):
keypair = c._crypto.generatePubKey() keypair = crypto.generate()
onionrusers.OnionrUser(c, keypair[0]) onionrusers.OnionrUser(keypair[0])
return return
def test_contact_init_no_save(self): def test_contact_init_no_save(self):
contact = c._crypto.generatePubKey()[0] contact = crypto.generate()[0]
contact = contactmanager.ContactManager(c, contact) contact = contactmanager.ContactManager(contact)
self.assertFalse(contact.publicKey in c.listPeers()) self.assertFalse(contact.publicKey in keydb.listkeys.list_peers())
def test_contact_create(self): def test_contact_create(self):
contact = c._crypto.generatePubKey()[0] contact = crypto.generate()[0]
contact = contactmanager.ContactManager(c, contact, saveUser=True) contact = contactmanager.ContactManager(contact, saveUser=True)
self.assertTrue(contact.publicKey in c.listPeers()) self.assertTrue(contact.publicKey in keydb.listkeys.list_peers())
def test_contact_set_info(self): def test_contact_set_info(self):
contact = c._crypto.generatePubKey()[0] contact = crypto.generate()[0]
contact = contactmanager.ContactManager(c, contact, saveUser=True) contact = contactmanager.ContactManager(contact, saveUser=True)
fileLocation = '%s/contacts/%s.json' % (c.dataDir, contact.publicKey) fileLocation = '%s/contacts/%s.json' % (identifyhome.identify_home(), contact.publicKey)
contact.set_info('alias', 'bob') contact.set_info('alias', 'bob')
self.assertTrue(os.path.exists(fileLocation)) self.assertTrue(os.path.exists(fileLocation))
@ -47,9 +48,9 @@ class OnionrUserTests(unittest.TestCase):
self.assertEqual(data['alias'], 'bob') self.assertEqual(data['alias'], 'bob')
def test_contact_get_info(self): def test_contact_get_info(self):
contact = c._crypto.generatePubKey()[0] contact = crypto.generate()[0]
contact = contactmanager.ContactManager(c, contact, saveUser=True) contact = contactmanager.ContactManager(contact, saveUser=True)
fileLocation = '%s/contacts/%s.json' % (c.dataDir, contact.publicKey) fileLocation = '%s/contacts/%s.json' % (identifyhome.identify_home(), contact.publicKey)
with open(fileLocation, 'w') as contactFile: with open(fileLocation, 'w') as contactFile:
contactFile.write('{"alias": "bob"}') contactFile.write('{"alias": "bob"}')
@ -59,16 +60,16 @@ class OnionrUserTests(unittest.TestCase):
self.assertEqual(contact.get_info('fail'), None) self.assertEqual(contact.get_info('fail'), None)
def test_encrypt(self): def test_encrypt(self):
contactPair = c._crypto.generatePubKey() contactPair = crypto.generate()
contact = contactmanager.ContactManager(c, contactPair[0], saveUser=True) contact = contactmanager.ContactManager(contactPair[0], saveUser=True)
encrypted = contact.encrypt('test') encrypted = contact.encrypt('test')
decrypted = c._crypto.pubKeyDecrypt(encrypted, privkey=contactPair[1], encodedData=True).decode() decrypted = crypto.encryption.pub_key_decrypt(encrypted, privkey=contactPair[1], encodedData=True).decode()
self.assertEqual('test', decrypted) self.assertEqual('test', decrypted)
def test_delete_contact(self): def test_delete_contact(self):
contact = c._crypto.generatePubKey()[0] contact = crypto.generate()[0]
contact = contactmanager.ContactManager(c, contact, saveUser=True) contact = contactmanager.ContactManager(contact, saveUser=True)
fileLocation = '%s/contacts/%s.json' % (c.dataDir, contact.publicKey) fileLocation = '%s/contacts/%s.json' % (identifyhome.identify_home(), contact.publicKey)
self.assertFalse(os.path.exists(fileLocation)) self.assertFalse(os.path.exists(fileLocation))
with open(fileLocation, 'w') as contactFile: with open(fileLocation, 'w') as contactFile:
contactFile.write('{"alias": "test"}') contactFile.write('{"alias": "test"}')

View File

@ -5,11 +5,8 @@ import unittest, uuid
TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/' TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/'
print("Test directory:", TEST_DIR) print("Test directory:", TEST_DIR)
os.environ["ONIONR_HOME"] = TEST_DIR os.environ["ONIONR_HOME"] = TEST_DIR
import core, onionr
from onionrutils import stringvalidators from onionrutils import stringvalidators
core.Core()
class OnionrValidations(unittest.TestCase): class OnionrValidations(unittest.TestCase):
def test_peer_validator(self): def test_peer_validator(self):
@ -50,7 +47,6 @@ class OnionrValidations(unittest.TestCase):
# Test ed25519 public key validity # Test ed25519 public key validity
valids = ['JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIRRQ====', 'JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIRRQ'] valids = ['JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIRRQ====', 'JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIRRQ']
invalid = [None, '', ' ', 'dfsg', '\n', 'JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIR$Q===='] invalid = [None, '', ' ', 'dfsg', '\n', 'JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIR$Q====']
c = core.Core()
for valid in valids: for valid in valids:
print('testing', valid) print('testing', valid)

View File

@ -8,6 +8,8 @@ def create_dirs():
os.mkdir(home) os.mkdir(home)
if not os.path.exists(filepaths.block_data_location): if not os.path.exists(filepaths.block_data_location):
os.mkdir(filepaths.block_data_location) os.mkdir(filepaths.block_data_location)
if not os.path.exists(filepaths.contacts_location):
os.mkdir(filepaths.contacts_location)
for db in dbcreator.create_funcs: for db in dbcreator.create_funcs:
try: try: