Mostly finished with wot command processing
This commit is contained in:
parent
d915a2aaed
commit
a517ad3aee
@ -1,13 +1,8 @@
|
||||
PyNaCl==1.5.0
|
||||
PySocks==1.7.1
|
||||
stem==1.8.0
|
||||
unpaddedbase32==0.2.0
|
||||
niceware==0.2.1
|
||||
psutil==5.9.1
|
||||
filenuke==0.0.0
|
||||
ujson==5.4.0
|
||||
cffi==1.15.1
|
||||
onionrblocks==7.0.0
|
||||
ordered-set==4.1.0
|
||||
cherrypy==18.8.0
|
||||
json-rpc==1.13.0
|
@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Generate a 16 word passphase with 256 bits of entropy.
|
||||
|
||||
Specify true to reduce to 128 bits"""
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
import niceware
|
||||
|
||||
byte_count = 32 # 256 bits of entropy with niceware
|
||||
|
||||
arg = False
|
||||
try:
|
||||
arg = sys.argv[1].lower()
|
||||
if arg == 'true':
|
||||
byte_count = 16
|
||||
except IndexError: pass
|
||||
|
||||
print(' '.join(niceware.generate_passphrase(byte_count)))
|
@ -1,95 +0,0 @@
|
||||
"""Onionr - Private P2P Communication.
|
||||
|
||||
This module defines user ID-related CLI commands
|
||||
"""
|
||||
import sys
|
||||
import getpass
|
||||
|
||||
import unpaddedbase32
|
||||
import niceware
|
||||
|
||||
import logger
|
||||
import onionrexceptions
|
||||
from onionrutils import stringvalidators, bytesconverter
|
||||
import config
|
||||
import keymanager
|
||||
import onionrcrypto
|
||||
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/>.
|
||||
"""
|
||||
|
||||
|
||||
DETERMINISTIC_REQUIREMENT = onionrvalues.PASSWORD_LENGTH
|
||||
|
||||
|
||||
def add_ID():
|
||||
"""Command to create a new user ID key pair."""
|
||||
key_manager = keymanager.KeyManager()
|
||||
pw = ""
|
||||
try:
|
||||
sys.argv[2] # pylint: disable=W0104
|
||||
if not sys.argv[2].lower() == 'true':
|
||||
raise ValueError
|
||||
except (IndexError, ValueError):
|
||||
newID = key_manager.addKey()[0]
|
||||
else:
|
||||
pw = "-".join(niceware.generate_passphrase(32))
|
||||
newID, privKey = onionrcrypto.generate_deterministic(pw)
|
||||
try:
|
||||
key_manager.addKey(pubKey=newID,
|
||||
privKey=privKey)
|
||||
except ValueError:
|
||||
logger.error(
|
||||
'That ID is already available, you can change to it ' +
|
||||
'with the change-id command.', terminal=True)
|
||||
return
|
||||
if pw:
|
||||
print("Phrase to restore ID:", pw)
|
||||
logger.info('Added ID: %s' %
|
||||
(bytesconverter.bytes_to_str(newID.replace('=', '')),), 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
|
||||
|
||||
|
||||
def change_ID():
|
||||
"""Command to change active ID from argv or stdin."""
|
||||
key_manager = keymanager.KeyManager()
|
||||
try:
|
||||
key = sys.argv[2]
|
||||
key = unpaddedbase32.repad(key.encode()).decode()
|
||||
except IndexError:
|
||||
logger.warn('Specify pubkey to use', terminal=True)
|
||||
else:
|
||||
if stringvalidators.validate_pub_key(key):
|
||||
key_list = key_manager.getPubkeyList()
|
||||
if key in key_list or key.replace('=', '') in key_list:
|
||||
config.set('general.public_key', key)
|
||||
config.save()
|
||||
logger.info('Set active key to: %s' % (key,), terminal=True)
|
||||
logger.info('Restart Onionr if it is running.', terminal=True)
|
||||
else:
|
||||
logger.warn('That key does not exist', terminal=True)
|
||||
else:
|
||||
logger.warn('Invalid key %s' % (key,), terminal=True)
|
||||
|
||||
|
||||
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
|
@ -1,42 +0,0 @@
|
||||
"""
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
validate various string data types
|
||||
"""
|
||||
import base64
|
||||
import string
|
||||
import unpaddedbase32, nacl.signing, nacl.encoding
|
||||
from onionrutils import bytesconverter
|
||||
"""
|
||||
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 validate_pub_key(key):
|
||||
"""Validate if a string is a valid base32 encoded Ed25519 key"""
|
||||
if type(key) is type(None):
|
||||
return False
|
||||
# Accept keys that have no = padding
|
||||
key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key))
|
||||
|
||||
retVal = False
|
||||
try:
|
||||
nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder)
|
||||
except nacl.exceptions.ValueError:
|
||||
pass
|
||||
except base64.binascii.Error as _:
|
||||
pass
|
||||
else:
|
||||
retVal = True
|
||||
return retVal
|
@ -3,7 +3,6 @@
|
||||
size related utilities
|
||||
"""
|
||||
import os
|
||||
from onionrutils import stringvalidators
|
||||
"""
|
||||
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
|
||||
|
@ -7,9 +7,6 @@ from nacl.signing import SigningKey, VerifyKey
|
||||
from nacl.encoding import Base32Encoder
|
||||
from nacl.exceptions import BadSignatureError
|
||||
|
||||
from wot.identity.processtrustsignature import process_trust_signature
|
||||
from wot.identity.processrevokesignature import process_revoke_signature
|
||||
from wot.identity.processidentityannounce import process_identity_announce
|
||||
from wot.identity.name import IdentityName
|
||||
from wot.identity.name import max_len as max_name_len
|
||||
from wot.identity.identityset import IdentitySet, identities
|
||||
|
@ -1,28 +0,0 @@
|
||||
import logger
|
||||
|
||||
from nacl.signing import VerifyKey
|
||||
|
||||
from wot.blockprocessingevent import WotCommand
|
||||
from wot.identity.identityset import identities
|
||||
|
||||
def process_identity_announce(identity_announce_payload):
|
||||
if len(identity_announce_payload) != 97:
|
||||
logger.warn(
|
||||
f'Identity announce signature size is invalid',
|
||||
terminal=True)
|
||||
|
||||
# verify that this is a signature for an announce command
|
||||
if identity_announce_payload[0] != WotCommand.ANNOUNCE:
|
||||
logger.warn(
|
||||
f'Invalid command in signature' , terminal=True)
|
||||
return
|
||||
# signer is first 32 bytes
|
||||
signer = identity_announce_payload[1:33]
|
||||
# signature is last 64 bytes
|
||||
signature = identity_announce_payload[33:]
|
||||
|
||||
# If bad signature, it raises nacl.exceptions.BadSignatureError
|
||||
VerifyKey(signer).verify(identity_announce_payload[0] + signer, signature)
|
||||
|
||||
# noop if already announced
|
||||
identities.add
|
@ -0,0 +1,4 @@
|
||||
from .processidentityannounce import process_identity_announce
|
||||
from .processrevokesignature import process_revoke_signature
|
||||
from .processtrustsignature import process_trust_signature
|
||||
from .processrevokeidentity import process_identity_revoke
|
@ -0,0 +1,17 @@
|
||||
import logger
|
||||
|
||||
from nacl.signing import VerifyKey
|
||||
|
||||
from wot.blockprocessingevent import WotCommand
|
||||
from wot.identity import Identity
|
||||
from wot.identity.identityset import identities
|
||||
|
||||
def process_identity_announce(identity_announce_payload):
|
||||
|
||||
# verify that this is a signature for an announce command
|
||||
if identity_announce_payload[0] != WotCommand.ANNOUNCE:
|
||||
logger.warn(
|
||||
f'Invalid command in signature' , terminal=True)
|
||||
return
|
||||
iden = Identity.deserialize(identity_announce_payload[1:])
|
||||
identities.add(iden)
|
@ -0,0 +1,21 @@
|
||||
import logger
|
||||
|
||||
from nacl.signing import VerifyKey
|
||||
|
||||
from wot.blockprocessingevent import WotCommand
|
||||
from wot.identity import Identity
|
||||
from wot.identity.identityset import identities
|
||||
|
||||
def process_identity_revoke(revoke_payload: bytes):
|
||||
wot_cmd = revoke_payload[0].to_bytes(1, 'big')
|
||||
if revoke_payload[0] != WotCommand.REVOKE:
|
||||
logger.warn(
|
||||
f'Invalid command in signature', terminal=True)
|
||||
return
|
||||
revoked_identity = revoke_payload[1:33]
|
||||
signature = revoke_payload[33:]
|
||||
|
||||
# raises nacl.exceptions.BadSignatureError if bad signature
|
||||
VerifyKey(revoked_identity).verify(wot_cmd + revoked_identity, signature)
|
||||
|
||||
identities.remove(Identity(revoked_identity, "etc"))
|
@ -11,6 +11,7 @@ def process_trust_signature(sig_payload: bytes):
|
||||
if len(sig_payload) != 129:
|
||||
logger.warn(
|
||||
f'Signature size is invalid for a signed identity')
|
||||
return
|
||||
|
||||
# verify that this is a signature for a trust command
|
||||
if sig_payload[0] != WotCommand.TRUST:
|
@ -15,10 +15,11 @@ os.environ["ONIONR_HOME"] = TEST_DIR
|
||||
import unittest
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append('static-data/default-plugins/wot/wot')
|
||||
sys.path.append('static-data/default-plugins/wot/')
|
||||
sys.path.append("src/")
|
||||
import identity
|
||||
from identity.identityset import identities
|
||||
from wot.identityprocessing import process_identity_announce
|
||||
from wot import identity
|
||||
from wot.identity.identityset import identities
|
||||
|
||||
|
||||
class WotCommand(IntEnum):
|
||||
@ -34,16 +35,14 @@ class TestAnnounceIdentityPayload(unittest.TestCase):
|
||||
identities.clear()
|
||||
|
||||
signing_key = SigningKey.generate()
|
||||
main_iden = identity.Identity(signing_key.verify_key, "test")
|
||||
main_iden = identity.Identity(signing_key, "test")
|
||||
|
||||
wot_cmd = int(WotCommand.ANNOUNCE).to_bytes(1, 'big')
|
||||
announce_signature = signing_key.sign(wot_cmd + bytes(main_iden))
|
||||
announce_signature_payload = wot_cmd + bytes(signing_key.verify_key) + \
|
||||
bytes(announce_signature)
|
||||
serialized_iden = wot_cmd + main_iden.serialize()
|
||||
|
||||
identity.process_identity_announce(announce_signature_payload)
|
||||
process_identity_announce(serialized_iden)
|
||||
|
||||
self.assertEqual(main_iden, identities[0])
|
||||
self.assertEqual(bytes(main_iden.key), bytes(list(identities)[0].key))
|
||||
self.assertEqual(len(identities), 1)
|
||||
self.assertEqual(len(main_iden.trusted), 0)
|
||||
|
||||
|
@ -0,0 +1,68 @@
|
||||
import os, uuid
|
||||
from random import randint
|
||||
from time import sleep
|
||||
from enum import IntEnum, auto
|
||||
from nacl.signing import SigningKey, VerifyKey
|
||||
from nacl.exceptions import BadSignatureError
|
||||
import nacl
|
||||
import secrets
|
||||
import onionrblocks
|
||||
|
||||
|
||||
TEST_DIR = 'testdata/%s-%s' % (str(uuid.uuid4())[:6], os.path.basename(__file__)) + '/'
|
||||
print("Test directory:", TEST_DIR)
|
||||
os.environ["ONIONR_HOME"] = TEST_DIR
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append('static-data/default-plugins/wot/')
|
||||
sys.path.append("src/")
|
||||
from wot.identityprocessing import process_identity_revoke
|
||||
from wot import identity
|
||||
from wot.identity.identityset import identities
|
||||
|
||||
|
||||
class WotCommand(IntEnum):
|
||||
TRUST = 1
|
||||
REVOKE_TRUST = auto()
|
||||
ANNOUNCE = auto()
|
||||
REVOKE = auto()
|
||||
|
||||
|
||||
class TestRevokeIdentityPayload(unittest.TestCase):
|
||||
|
||||
def test_revoke_identity_invalid(self):
|
||||
identities.clear()
|
||||
|
||||
signing_key = SigningKey.generate()
|
||||
main_iden = identity.Identity(signing_key, "test")
|
||||
identities.add(main_iden)
|
||||
|
||||
wot_cmd = int(WotCommand.REVOKE).to_bytes(1, 'big')
|
||||
|
||||
signed = signing_key.sign(wot_cmd + bytes(main_iden.key))
|
||||
revoke_payload = wot_cmd + bytes(signing_key.verify_key) + signed.signature
|
||||
|
||||
self.assertRaises(nacl.exceptions.Inv process_identity_revoke(revoke_payload)
|
||||
|
||||
self.assertEqual(len(identities), 1)
|
||||
|
||||
def test_revoke_identity_payload(self):
|
||||
identities.clear()
|
||||
|
||||
signing_key = SigningKey.generate()
|
||||
main_iden = identity.Identity(signing_key, "test")
|
||||
identities.add(main_iden)
|
||||
|
||||
wot_cmd = int(WotCommand.REVOKE).to_bytes(1, 'big')
|
||||
|
||||
signed = signing_key.sign(wot_cmd + bytes(main_iden.key))
|
||||
revoke_payload = wot_cmd + bytes(signing_key.verify_key) + signed.signature
|
||||
|
||||
process_identity_revoke(revoke_payload)
|
||||
|
||||
self.assertEqual(len(identities), 0)
|
||||
|
||||
|
||||
unittest.main()
|
@ -15,10 +15,10 @@ os.environ["ONIONR_HOME"] = TEST_DIR
|
||||
import unittest
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append('static-data/default-plugins/wot/wot')
|
||||
sys.path.append('static-data/default-plugins/wot/')
|
||||
sys.path.append("src/")
|
||||
import identity
|
||||
from identity.identityset import identities
|
||||
from wot import identity
|
||||
from wot.identity.identityset import identities
|
||||
|
||||
|
||||
class WotCommand(IntEnum):
|
||||
|
Loading…
Reference in New Issue
Block a user