From 60c1ec07e9f52593ed99fe3a780ed71e2fcd59dc Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Sat, 19 Sep 2020 21:01:31 +0000 Subject: [PATCH] started c# pow implementation --- src/onionrblocks/insert/main.py | 1 + .../cryptoutils/getpubfrompriv.py | 26 ++++++++- src/onionrcrypto/generate.py | 58 +++++++++++++++---- src/onionrproofs/shellpow.py | 0 src/onionrproofs/subprocesspow.py | 7 ++- src/onionrutils/importnewblocks.py | 52 ++++++++++------- 6 files changed, 108 insertions(+), 36 deletions(-) create mode 100644 src/onionrproofs/shellpow.py diff --git a/src/onionrblocks/insert/main.py b/src/onionrblocks/insert/main.py index 8f590158..97c3a98c 100644 --- a/src/onionrblocks/insert/main.py +++ b/src/onionrblocks/insert/main.py @@ -205,6 +205,7 @@ def insert_block(data: Union[str, bytes], header: str = 'txt', # send block data (and metadata) to POW module to get tokenized block data payload = subprocesspow.SubprocessPOW(data, metadata).start() + print(payload) if payload != False: # noqa try: retData = onionrstorage.set_data(payload) diff --git a/src/onionrcrypto/cryptoutils/getpubfrompriv.py b/src/onionrcrypto/cryptoutils/getpubfrompriv.py index 8bb8d7d2..5972d4a4 100644 --- a/src/onionrcrypto/cryptoutils/getpubfrompriv.py +++ b/src/onionrcrypto/cryptoutils/getpubfrompriv.py @@ -1,6 +1,28 @@ +"""Onionr - Private P2P Communication. + +generate a public ed25519 key from a private one +""" from nacl import signing, encoding from onionrtypes import UserID, UserIDSecretKey +""" + 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. -def get_pub_key_from_priv(priv_key: UserIDSecretKey, raw_encoding:bool=False)->UserID: - return signing.SigningKey(priv_key, encoder=encoding.Base32Encoder).verify_key.encode(encoding.Base32Encoder) + 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 . +""" + + +def get_pub_key_from_priv(priv_key: UserIDSecretKey, + raw_encoding: bool = False) -> UserID: + return signing.SigningKey( + priv_key, encoder=encoding.Base32Encoder).verify_key.encode( + encoding.Base32Encoder) diff --git a/src/onionrcrypto/generate.py b/src/onionrcrypto/generate.py index 5b6c1e4b..4fdacd9b 100644 --- a/src/onionrcrypto/generate.py +++ b/src/onionrcrypto/generate.py @@ -1,27 +1,65 @@ -import nacl.signing, nacl.encoding, nacl.pwhash +"""Onionr - Private P2P Communication. + +functions to generate ed25519 key pairs +""" +import nacl.signing +import nacl.encoding +import nacl.pwhash + import onionrexceptions from onionrutils import bytesconverter from etc import onionrvalues +""" + 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 . +""" + + 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() - public_key = private_key.verify_key.encode(encoder=nacl.encoding.Base32Encoder()) - return (public_key.decode(), private_key.encode(encoder=nacl.encoding.Base32Encoder()).decode()) + public_key = private_key.verify_key.encode( + encoder=nacl.encoding.Base32Encoder()) + 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 phase, not intended for human-generated key''' + """Generate a Ed25519 public key pair from a phase. + + not intended for human-generated key + """ passStrength = onionrvalues.PASSWORD_LENGTH - passphrase = bytesconverter.str_to_bytes(passphrase) # Convert to bytes if not already + # Convert to bytes if not already + passphrase = bytesconverter.str_to_bytes(passphrase) # Validate passphrase length if not bypassCheck: if len(passphrase) < passStrength: - raise onionrexceptions.PasswordStrengthError("Passphase must be at least %s characters" % (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 secret, but must be 16 bytes + # Does not need to be secret, but must be 16 bytes + salt = b"U81Q7llrQcdTP0Ux" 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 + # Generate seed for ed25519 key + key = kdf(32, passphrase, salt, opslimit=ops, memlimit=mem) key = nacl.signing.SigningKey(key) - return (key.verify_key.encode(nacl.encoding.Base32Encoder).decode(), key.encode(nacl.encoding.Base32Encoder).decode()) + return ( + key.verify_key.encode(nacl.encoding.Base32Encoder).decode(), + key.encode(nacl.encoding.Base32Encoder).decode()) diff --git a/src/onionrproofs/shellpow.py b/src/onionrproofs/shellpow.py new file mode 100644 index 00000000..e69de29b diff --git a/src/onionrproofs/subprocesspow.py b/src/onionrproofs/subprocesspow.py index 9b6b96cf..33571823 100755 --- a/src/onionrproofs/subprocesspow.py +++ b/src/onionrproofs/subprocesspow.py @@ -8,13 +8,15 @@ import os from multiprocessing import Pipe, Process import threading import time +import secrets + import onionrproofs import ujson as json import logger -import onionrcrypto as crypto from onionrutils import bytesconverter +from onionrcrypto.hashers import sha3_hash """ This program is free software: you can redistribute it and/or modify @@ -111,6 +113,7 @@ class SubprocessPOW: nonce = 0 data = self.data metadata = self.metadata + metadata['nonce'] = secrets.randbits(16) puzzle = self.puzzle difficulty = self.difficulty @@ -127,7 +130,7 @@ class SubprocessPOW: payload = json.dumps(metadata).encode() + b'\n' + data # Check sha3_256 hash of block, compare to puzzle # Send payload if puzzle finished - token = crypto.hashers.sha3_hash(payload) + token = sha3_hash(payload) # ensure token is string token = bytesconverter.bytes_to_str(token) if puzzle == token[0:difficulty]: diff --git a/src/onionrutils/importnewblocks.py b/src/onionrutils/importnewblocks.py index bd2fa223..7e6bec58 100644 --- a/src/onionrutils/importnewblocks.py +++ b/src/onionrutils/importnewblocks.py @@ -1,9 +1,16 @@ -''' - Onionr - Private P2P Communication +"""Onionr - Private P2P Communication. - import new blocks from disk, providing transport agnosticism -''' -''' +import new blocks from disk, providing transport agnosticism +""" +import glob + +import logger +from onionrutils import blockmetadata +from coredb import blockmetadb +import filepaths +import onionrcrypto as crypto +from etc.onionrvalues import BLOCK_EXPORT_FILE_EXT +""" 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 @@ -16,18 +23,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -''' -import glob -import logger -from onionrutils import blockmetadata -from coredb import blockmetadb -import filepaths -import onionrcrypto as crypto -from etc.onionrvalues import BLOCK_EXPORT_FILE_EXT +""" + + def import_new_blocks(scanDir=''): - ''' - This function is intended to scan for new blocks ON THE DISK and import them - ''' + """Scan for new blocks ON THE DISK and import them""" blockList = blockmetadb.get_block_list() exist = False if scanDir == '': @@ -35,18 +35,26 @@ def import_new_blocks(scanDir=''): if not scanDir.endswith('/'): scanDir += '/' for block in glob.glob(scanDir + "*%s" % (BLOCK_EXPORT_FILE_EXT,)): - if block.replace(scanDir, '').replace(BLOCK_EXPORT_FILE_EXT, '') not in blockList: + if block.replace(scanDir, '').replace(BLOCK_EXPORT_FILE_EXT, '') \ + not in blockList: exist = True logger.info('Found new block on dist %s' % block, terminal=True) with open(block, 'rb') as newBlock: - block = block.replace(scanDir, '').replace(BLOCK_EXPORT_FILE_EXT, '') - if crypto.hashers.sha3_hash(newBlock.read()) == block.replace(BLOCK_EXPORT_FILE_EXT, ''): - blockmetadb.add_to_block_DB(block.replace(BLOCK_EXPORT_FILE_EXT, ''), dataSaved=True) + block = block.replace(scanDir, '').replace( + BLOCK_EXPORT_FILE_EXT, '') + if crypto.hashers.sha3_hash(newBlock.read()) == block.replace( + BLOCK_EXPORT_FILE_EXT, ''): + blockmetadb.add_to_block_DB(block.replace( + BLOCK_EXPORT_FILE_EXT, ''), dataSaved=True) logger.info('Imported block %s' % block, terminal=True) blockmetadata.process_block_metadata(block) else: - logger.warn('Failed to verify hash for %s' % block, terminal=True) + logger.warn('Failed to verify hash for %s' % block, + terminal=True) if not exist: logger.info('No blocks found to import', terminal=True) -import_new_blocks.onionr_help = f"Scans the Onionr data directory under {filepaths.block_data_location} for new block files (.db not supported) to import" + +import_new_blocks.onionr_help = \ + f"Scan the Onionr data directory under {filepaths.block_data_location}" + \ + "for new block files (.db not supported) to import"