2019-12-19 10:34:19 +00:00
|
|
|
"""Onionr - Private P2P Communication.
|
2019-03-08 01:08:06 +00:00
|
|
|
|
2019-12-19 10:34:19 +00:00
|
|
|
This module defines user ID-related CLI commands
|
|
|
|
"""
|
|
|
|
import sys
|
|
|
|
import getpass
|
|
|
|
|
|
|
|
import unpaddedbase32
|
|
|
|
import niceware
|
|
|
|
|
|
|
|
import vanityonionr
|
|
|
|
import logger
|
|
|
|
import onionrexceptions
|
|
|
|
from onionrutils import stringvalidators, bytesconverter
|
|
|
|
import config
|
|
|
|
import keymanager
|
|
|
|
import onionrcrypto
|
|
|
|
from etc import onionrvalues
|
|
|
|
"""
|
2019-03-08 01:08:06 +00:00
|
|
|
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/>.
|
2019-12-19 10:34:19 +00:00
|
|
|
"""
|
2019-03-08 01:08:06 +00:00
|
|
|
|
2019-09-09 08:23:09 +00:00
|
|
|
|
2019-12-19 10:34:19 +00:00
|
|
|
DETERMINISTIC_REQUIREMENT = onionrvalues.PASSWORD_LENGTH
|
2019-09-09 08:23:09 +00:00
|
|
|
|
|
|
|
|
2019-08-05 23:09:04 +00:00
|
|
|
def add_ID():
|
2019-12-19 10:34:19 +00:00
|
|
|
"""Command to create a new user ID key pair."""
|
2019-07-27 20:29:15 +00:00
|
|
|
key_manager = keymanager.KeyManager()
|
2019-03-08 01:08:06 +00:00
|
|
|
try:
|
2019-12-19 10:34:19 +00:00
|
|
|
sys.argv[2] # pylint: disable=W0104
|
|
|
|
if not sys.argv[2].lower() == 'true':
|
|
|
|
raise ValueError
|
|
|
|
except (IndexError, ValueError):
|
2019-07-27 20:29:15 +00:00
|
|
|
newID = key_manager.addKey()[0]
|
2019-03-08 01:08:06 +00:00
|
|
|
else:
|
2019-12-19 10:34:19 +00:00
|
|
|
logger.warn(
|
|
|
|
'Deterministic keys require random and long passphrases.',
|
|
|
|
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)
|
2019-08-12 23:48:20 +00:00
|
|
|
try:
|
2019-12-19 10:34:19 +00:00
|
|
|
pass1 = getpass.getpass(
|
|
|
|
prompt='Enter at least %s characters: ' %
|
|
|
|
(DETERMINISTIC_REQUIREMENT,))
|
2019-08-12 23:48:20 +00:00
|
|
|
pass2 = getpass.getpass(prompt='Confirm entry: ')
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
sys.exit(42)
|
2019-07-27 20:29:15 +00:00
|
|
|
if onionrcrypto.cryptoutils.safe_compare(pass1, pass2):
|
2019-03-08 01:08:06 +00:00
|
|
|
try:
|
2019-12-19 10:34:19 +00:00
|
|
|
logger.info(
|
|
|
|
'Generating deterministic key. This can take a while.',
|
|
|
|
terminal=True)
|
2019-07-27 20:29:15 +00:00
|
|
|
newID, privKey = onionrcrypto.generate_deterministic(pass1)
|
2019-03-08 01:08:06 +00:00
|
|
|
except onionrexceptions.PasswordStrengthError:
|
2019-12-19 10:34:19 +00:00
|
|
|
logger.error('Passphrase must use at least %s characters.' % (
|
|
|
|
DETERMINISTIC_REQUIREMENT,), terminal=True)
|
2019-03-08 01:08:06 +00:00
|
|
|
sys.exit(1)
|
|
|
|
else:
|
2019-06-20 00:59:05 +00:00
|
|
|
logger.error('Passwords do not match.', terminal=True)
|
2019-03-08 01:08:06 +00:00
|
|
|
sys.exit(1)
|
2019-06-26 19:54:13 +00:00
|
|
|
try:
|
2019-12-19 10:34:19 +00:00
|
|
|
key_manager.addKey(pubKey=newID,
|
|
|
|
privKey=privKey)
|
2019-06-26 19:54:13 +00:00
|
|
|
except ValueError:
|
2019-12-19 10:34:19 +00:00
|
|
|
logger.error(
|
|
|
|
'That ID is already available, you can change to it ' +
|
|
|
|
'with the change-id command.', terminal=True)
|
2019-06-26 19:54:13 +00:00
|
|
|
return
|
2019-12-19 10:34:19 +00:00
|
|
|
logger.info('Added ID: %s' %
|
|
|
|
(bytesconverter.bytes_to_str(newID),), terminal=True)
|
|
|
|
|
|
|
|
|
|
|
|
add_ID.onionr_help = "If the first argument is true, " # type: ignore
|
|
|
|
add_ID.onionr_help += "Onionr will show a deterministic " # type: ignore
|
|
|
|
add_ID.onionr_help += "generation prompt. Otherwise it will " # type: ignore
|
|
|
|
add_ID.onionr_help += "generate & save a new random key pair." # type: ignore
|
2019-03-08 01:08:06 +00:00
|
|
|
|
2019-09-21 05:06:49 +00:00
|
|
|
|
2019-08-05 23:09:04 +00:00
|
|
|
def change_ID():
|
2019-12-19 10:34:19 +00:00
|
|
|
"""Command to change active ID from argv or stdin."""
|
2019-07-27 20:29:15 +00:00
|
|
|
key_manager = keymanager.KeyManager()
|
2019-03-08 01:08:06 +00:00
|
|
|
try:
|
|
|
|
key = sys.argv[2]
|
2019-06-19 06:57:13 +00:00
|
|
|
key = unpaddedbase32.repad(key.encode()).decode()
|
2019-03-08 01:08:06 +00:00
|
|
|
except IndexError:
|
2019-06-20 00:59:05 +00:00
|
|
|
logger.warn('Specify pubkey to use', terminal=True)
|
2019-03-08 01:08:06 +00:00
|
|
|
else:
|
2019-06-25 08:21:36 +00:00
|
|
|
if stringvalidators.validate_pub_key(key):
|
2019-09-09 08:52:40 +00:00
|
|
|
key_list = key_manager.getPubkeyList()
|
|
|
|
if key in key_list or key.replace('=', '') in key_list:
|
2019-08-05 23:09:04 +00:00
|
|
|
config.set('general.public_key', key)
|
|
|
|
config.save()
|
2019-06-20 00:59:05 +00:00
|
|
|
logger.info('Set active key to: %s' % (key,), terminal=True)
|
|
|
|
logger.info('Restart Onionr if it is running.', terminal=True)
|
2019-03-08 01:08:06 +00:00
|
|
|
else:
|
2019-06-20 00:59:05 +00:00
|
|
|
logger.warn('That key does not exist', terminal=True)
|
2019-03-08 01:08:06 +00:00
|
|
|
else:
|
2019-06-20 00:59:05 +00:00
|
|
|
logger.warn('Invalid key %s' % (key,), terminal=True)
|
2019-09-09 08:23:09 +00:00
|
|
|
|
2019-12-19 10:34:19 +00:00
|
|
|
|
|
|
|
change_ID.onionr_help = "<pubkey>: Switches Onionr to " # type: ignore
|
|
|
|
change_ID.onionr_help += "use a different user ID key. " # type: ignore
|
|
|
|
change_ID.onionr_help += "You should immediately restart " # type: ignore
|
|
|
|
change_ID.onionr_help += "Onionr if it is running." # type: ignore
|
|
|
|
|
2019-09-21 05:06:49 +00:00
|
|
|
|
2019-09-09 08:23:09 +00:00
|
|
|
def add_vanity():
|
2019-12-19 10:34:19 +00:00
|
|
|
"""Command to generate menmonic vanity key pair."""
|
2019-09-09 08:23:09 +00:00
|
|
|
key_manager = keymanager.KeyManager()
|
2019-12-19 10:34:19 +00:00
|
|
|
|
|
|
|
def tell(tell):
|
|
|
|
return logger.info(tell, terminal=True)
|
|
|
|
|
2019-09-09 08:23:09 +00:00
|
|
|
words = ''
|
|
|
|
length = len(sys.argv) - 2
|
2019-12-19 10:34:19 +00:00
|
|
|
if length == 0:
|
|
|
|
return
|
2019-09-09 08:23:09 +00:00
|
|
|
for i in range(2, len(sys.argv)):
|
|
|
|
words += ' '
|
|
|
|
words += sys.argv[i]
|
|
|
|
try:
|
|
|
|
if length == 1:
|
|
|
|
tell('Finding vanity, this should only take a few moments.')
|
|
|
|
else:
|
|
|
|
tell('Finding vanity, this will probably take a really long time.')
|
|
|
|
try:
|
|
|
|
vanity = vanityonionr.find_multiprocess(words)
|
|
|
|
except ValueError:
|
2019-12-19 10:34:19 +00:00
|
|
|
logger.warn('Vanity words must be valid english bip39',
|
|
|
|
terminal=True)
|
2019-09-09 08:23:09 +00:00
|
|
|
else:
|
|
|
|
b32_pub = unpaddedbase32.b32encode(vanity[0])
|
2019-12-19 10:34:19 +00:00
|
|
|
tell('Found vanity address:\n' +
|
|
|
|
niceware.bytes_to_passphrase(vanity[0]))
|
2019-09-09 08:23:09 +00:00
|
|
|
tell('Base32 Public key: %s' % (b32_pub.decode(),))
|
|
|
|
key_manager.addKey(b32_pub, unpaddedbase32.b32encode(vanity[1]))
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
pass
|
2019-12-19 10:34:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
add_vanity.onionr_help = "<space separated words> - " # type: ignore
|
|
|
|
add_vanity.onionr_help += "Generates and stores an " # type: ignore
|
|
|
|
add_vanity.onionr_help += "Onionr vanity address " # type: ignore
|
|
|
|
add_vanity.onionr_help += "(see is.gd/YklHGe)" # type: ignore
|