started c# pow implementation

master
Kevin Froman 2020-09-19 21:01:31 +00:00
parent fd0f13cf63
commit 60c1ec07e9
6 changed files with 108 additions and 36 deletions

View File

@ -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 # send block data (and metadata) to POW module to get tokenized block data
payload = subprocesspow.SubprocessPOW(data, metadata).start() payload = subprocesspow.SubprocessPOW(data, metadata).start()
print(payload)
if payload != False: # noqa if payload != False: # noqa
try: try:
retData = onionrstorage.set_data(payload) retData = onionrstorage.set_data(payload)

View File

@ -1,6 +1,28 @@
"""Onionr - Private P2P Communication.
generate a public ed25519 key from a private one
"""
from nacl import signing, encoding from nacl import signing, encoding
from onionrtypes import UserID, UserIDSecretKey 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: This program is distributed in the hope that it will be useful,
return signing.SigningKey(priv_key, encoder=encoding.Base32Encoder).verify_key.encode(encoding.Base32Encoder) 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 <https://www.gnu.org/licenses/>.
"""
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)

View File

@ -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 import onionrexceptions
from onionrutils import bytesconverter from onionrutils import bytesconverter
from etc import onionrvalues 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 <https://www.gnu.org/licenses/>.
"""
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(
return (public_key.decode(), private_key.encode(encoder=nacl.encoding.Base32Encoder()).decode()) encoder=nacl.encoding.Base32Encoder())
return (public_key.decode(), private_key.encode(
encoder=nacl.encoding.Base32Encoder()).decode())
def generate_deterministic(passphrase, bypassCheck=False): 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 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 # Validate passphrase length
if not bypassCheck: if not bypassCheck:
if len(passphrase) < passStrength: 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 values
kdf = nacl.pwhash.argon2id.kdf 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 ops = nacl.pwhash.argon2id.OPSLIMIT_SENSITIVE
mem = nacl.pwhash.argon2id.MEMLIMIT_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) 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())

View File

View File

@ -8,13 +8,15 @@ import os
from multiprocessing import Pipe, Process from multiprocessing import Pipe, Process
import threading import threading
import time import time
import secrets
import onionrproofs import onionrproofs
import ujson as json import ujson as json
import logger import logger
import onionrcrypto as crypto
from onionrutils import bytesconverter from onionrutils import bytesconverter
from onionrcrypto.hashers import sha3_hash
""" """
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -111,6 +113,7 @@ class SubprocessPOW:
nonce = 0 nonce = 0
data = self.data data = self.data
metadata = self.metadata metadata = self.metadata
metadata['nonce'] = secrets.randbits(16)
puzzle = self.puzzle puzzle = self.puzzle
difficulty = self.difficulty difficulty = self.difficulty
@ -127,7 +130,7 @@ class SubprocessPOW:
payload = json.dumps(metadata).encode() + b'\n' + data payload = json.dumps(metadata).encode() + b'\n' + data
# Check sha3_256 hash of block, compare to puzzle # Check sha3_256 hash of block, compare to puzzle
# Send payload if puzzle finished # Send payload if puzzle finished
token = crypto.hashers.sha3_hash(payload) token = sha3_hash(payload)
# ensure token is string # ensure token is string
token = bytesconverter.bytes_to_str(token) token = bytesconverter.bytes_to_str(token)
if puzzle == token[0:difficulty]: if puzzle == token[0:difficulty]:

View File

@ -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 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or 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 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/>.
''' """
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=''): def import_new_blocks(scanDir=''):
''' """Scan for new blocks ON THE DISK and import them"""
This function is intended to scan for new blocks ON THE DISK and import them
'''
blockList = blockmetadb.get_block_list() blockList = blockmetadb.get_block_list()
exist = False exist = False
if scanDir == '': if scanDir == '':
@ -35,18 +35,26 @@ def import_new_blocks(scanDir=''):
if not scanDir.endswith('/'): if not scanDir.endswith('/'):
scanDir += '/' scanDir += '/'
for block in glob.glob(scanDir + "*%s" % (BLOCK_EXPORT_FILE_EXT,)): 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 exist = True
logger.info('Found new block on dist %s' % block, terminal=True) logger.info('Found new block on dist %s' % block, terminal=True)
with open(block, 'rb') as newBlock: with open(block, 'rb') as newBlock:
block = block.replace(scanDir, '').replace(BLOCK_EXPORT_FILE_EXT, '') block = block.replace(scanDir, '').replace(
if crypto.hashers.sha3_hash(newBlock.read()) == block.replace(BLOCK_EXPORT_FILE_EXT, ''): BLOCK_EXPORT_FILE_EXT, '')
blockmetadb.add_to_block_DB(block.replace(BLOCK_EXPORT_FILE_EXT, ''), dataSaved=True) 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) logger.info('Imported block %s' % block, terminal=True)
blockmetadata.process_block_metadata(block) blockmetadata.process_block_metadata(block)
else: 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: if not exist:
logger.info('No blocks found to import', terminal=True) 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"