removed deterministic keys due to poor hashing

This commit is contained in:
Kevin Froman 2020-09-14 11:54:14 +00:00
parent c7e0b6c1b2
commit 4bc2bf5db5
3 changed files with 69 additions and 54 deletions

View File

@ -4,7 +4,7 @@ import argparse
import os import os
from threading import Thread from threading import Thread
from time import sleep from time import sleep
from subprocess import PIPE from subprocess import DEVNULL
import ujson import ujson
from psutil import Popen from psutil import Popen
@ -12,6 +12,7 @@ from psutil import Process
import psutil import psutil
import sys import sys
import curses
script_dir = os.path.dirname(os.path.realpath(__file__)) script_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(script_dir + '/src/') sys.path.append(script_dir + '/src/')
@ -21,34 +22,66 @@ from etc import onionrvalues
sub_script = script_dir + '/' + onionrvalues.SCRIPT_NAME sub_script = script_dir + '/' + onionrvalues.SCRIPT_NAME
def show_info(p: Process): def show_info(p: Process):
def pbar(window):
window.addstr(8, 10, "Onionr statistics")
window.addstr(9, 10, "-" * 17)
curses.curs_set(0)
while True: while True:
threads = p.num_threads() threads = p.num_threads()
open_files = len(p.open_files()) open_files = len(p.open_files())
cpu_percent = p.cpu_percent()
block_count = len(blockmetadb.get_block_list())
for proc in p.children(recursive=True): for proc in p.children(recursive=True):
threads += proc.num_threads() threads += proc.num_threads()
cpu_percent += proc.cpu_percent()
try: try:
open_files += len(proc.open_files()) open_files += len(proc.open_files())
except psutil.AccessDenied: except psutil.AccessDenied:
pass pass
print(f'Approximate thread count: {threads}') cpu_percent = cpu_percent * 100
print(f'Approximate open files: {open_files}') window.addstr(11, 10, f"Threads: {threads}")
window.addstr(10, 10, f"Open files: {open_files}")
window.addstr(12, 10, f"CPU: {cpu_percent}%")
window.addstr(13, 10, f"Blocks: {block_count}")
window.refresh()
sleep(0.5)
sleep(15)
curses.wrapper(pbar)
while True:
sleep(1) sleep(1)
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
"--skip-onboarding", help="Skip Onionr onboarding", "--show-stats", help="Display curses output of Onionr stats",
type=bool, default=False) type=int, default=0)
parser.add_argument( parser.add_argument(
'--open-ui', help='Open onionr web ui after started' , "--skip-onboarding", help="Skip Onionr onboarding",
type=bool, default=True) type=int, default=0)
parser.add_argument(
"--security-level", help="Set Onionr security level",
type=int, default=0)
parser.add_argument(
'--open-ui', help='Open onionr web ui after started',
type=int, default=1)
parser.add_argument(
'--random-localhost-ip', help='bind to random localhost IP for extra security',
type=int, default=1)
parser.add_argument(
'--use-tor', help='Use Tor transport',
type=int, default=1)
parser.add_argument(
'--private-key', help='Use existing private key',
type=int, default=1)
args = parser.parse_args() args = parser.parse_args()
p = Popen([sub_script, 'version']) p = Popen([sub_script, 'version'], stdout=DEVNULL)
p.wait() p.wait()
from filepaths import config_file from filepaths import config_file
from coredb import blockmetadb
@ -58,18 +91,25 @@ with open(config_file, 'r') as cf:
if args.skip_onboarding: if args.skip_onboarding:
config['onboarding']['done'] = True config['onboarding']['done'] = True
print('Disabling onboarding') print('Disabling onboarding')
if not args.random_localhost_ip:
print('Disabling randomized localhost')
config['general']['random_bind_ip'] = False
if not args.use_tor:
config['transports']['tor'] = False
config['general']['display_header'] = False
config['general']['security_level'] = args.security_level
with open(config_file, 'w') as cf: with open(config_file, 'w') as cf:
cf.write(ujson.dumps(config)) cf.write(ujson.dumps(config))
if args.open_ui: if args.open_ui:
p = Popen([sub_script, 'start']) p = Popen([sub_script, 'start'], stdout=DEVNULL)
sleep(2) sleep(2)
Popen([sub_script, 'openhome']) Popen([sub_script, 'openhome'], stdout=DEVNULL)
else: else:
p = Popen([sub_script, 'start'], stdout=PIPE) p = Popen([sub_script, 'start'], stdout=DEVNULL)
p = p.children()[0] p = p.children()[0]
Thread(target=show_info, args=[p], daemon=True).start() if args.show_stats:
Thread(target=show_info, args=[p], daemon=True).start()
p.wait() p.wait()

View File

@ -38,6 +38,7 @@ DETERMINISTIC_REQUIREMENT = onionrvalues.PASSWORD_LENGTH
def add_ID(): def add_ID():
"""Command to create a new user ID key pair.""" """Command to create a new user ID key pair."""
key_manager = keymanager.KeyManager() key_manager = keymanager.KeyManager()
pw = ""
try: try:
sys.argv[2] # pylint: disable=W0104 sys.argv[2] # pylint: disable=W0104
if not sys.argv[2].lower() == 'true': if not sys.argv[2].lower() == 'true':
@ -45,36 +46,8 @@ def add_ID():
except (IndexError, ValueError): except (IndexError, ValueError):
newID = key_manager.addKey()[0] newID = key_manager.addKey()[0]
else: else:
logger.warn( pw = "-".join(niceware.generate_passphrase(32))
'Deterministic keys require random and long passphrases.', newID, privKey = onionrcrypto.generate_deterministic(pw)
terminal=True)
logger.warn(
'If a good passphrase is not used, your key can be easily stolen.',
terminal=True)
logger.warn(
'You should use a series of hard to guess words, ' +
'see this for reference: https://www.xkcd.com/936/',
terminal=True)
try:
pass1 = getpass.getpass(
prompt='Enter at least %s characters: ' %
(DETERMINISTIC_REQUIREMENT,))
pass2 = getpass.getpass(prompt='Confirm entry: ')
except KeyboardInterrupt:
sys.exit(42)
if onionrcrypto.cryptoutils.safe_compare(pass1, pass2):
try:
logger.info(
'Generating deterministic key. This can take a while.',
terminal=True)
newID, privKey = onionrcrypto.generate_deterministic(pass1)
except onionrexceptions.PasswordStrengthError:
logger.error('Passphrase must use at least %s characters.' % (
DETERMINISTIC_REQUIREMENT,), terminal=True)
sys.exit(1)
else:
logger.error('Passwords do not match.', terminal=True)
sys.exit(1)
try: try:
key_manager.addKey(pubKey=newID, key_manager.addKey(pubKey=newID,
privKey=privKey) privKey=privKey)
@ -83,8 +56,10 @@ def add_ID():
'That ID is already available, you can change to it ' + 'That ID is already available, you can change to it ' +
'with the change-id command.', terminal=True) 'with the change-id command.', terminal=True)
return return
if pw:
print("Phrase to restore ID:", pw)
logger.info('Added ID: %s' % logger.info('Added ID: %s' %
(bytesconverter.bytes_to_str(newID),), terminal=True) (bytesconverter.bytes_to_str(newID.replace('=', '')),), terminal=True)
add_ID.onionr_help = "If the first argument is true, " # type: ignore add_ID.onionr_help = "If the first argument is true, " # type: ignore

View File

@ -9,7 +9,7 @@ def generate_pub_key():
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): def generate_deterministic(passphrase, bypassCheck=False):
'''Generate a Ed25519 public key pair from a password''' '''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 passphrase = bytesconverter.str_to_bytes(passphrase) # Convert to bytes if not already
# Validate passphrase length # Validate passphrase length
@ -18,7 +18,7 @@ def generate_deterministic(passphrase, bypassCheck=False):
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 unique or secret, but must be 16 bytes salt = b"U81Q7llrQcdTP0Ux" # Does not need to be secret, but must be 16 bytes
ops = nacl.pwhash.argon2id.OPSLIMIT_SENSITIVE ops = nacl.pwhash.argon2id.OPSLIMIT_SENSITIVE
mem = nacl.pwhash.argon2id.MEMLIMIT_SENSITIVE mem = nacl.pwhash.argon2id.MEMLIMIT_SENSITIVE