main: integration identity verification
This commit is contained in:
3
setup.py
3
setup.py
@@ -24,6 +24,7 @@ setup(
|
||||
'Topic :: Communications',
|
||||
],
|
||||
entry_points={'console_scripts': [
|
||||
'trezor-agent = sshagent.__main__:trezor_agent'
|
||||
'trezor-agent = sshagent.__main__:trezor_agent',
|
||||
'trezor-verify = sshagent.__main__:trezor_verify'
|
||||
]},
|
||||
)
|
||||
|
||||
@@ -39,7 +39,7 @@ def identity_from_gitconfig():
|
||||
return 'ssh://{0}@{1}/{2}'.format(user, host, path)
|
||||
|
||||
|
||||
def parse_args():
|
||||
def create_parser():
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('-v', '--verbose', default=0, action='count')
|
||||
|
||||
@@ -53,18 +53,21 @@ def parse_args():
|
||||
help='connect to specified host via SSH')
|
||||
p.add_argument('command', type=str, nargs='*', metavar='ARGUMENT',
|
||||
help='command to run under the SSH agent')
|
||||
return p.parse_args()
|
||||
return p
|
||||
|
||||
|
||||
def trezor_agent():
|
||||
args = parse_args()
|
||||
|
||||
def setup_logging(verbosity):
|
||||
fmt = ('%(asctime)s %(levelname)-12s %(message)-100s '
|
||||
'[%(filename)s:%(lineno)d]')
|
||||
levels = [logging.WARNING, logging.INFO, logging.DEBUG]
|
||||
level = levels[min(args.verbose, len(levels) - 1)]
|
||||
level = levels[min(verbosity, len(levels) - 1)]
|
||||
logging.basicConfig(format=fmt, level=level)
|
||||
|
||||
|
||||
def trezor_agent():
|
||||
args = create_parser().parse_args()
|
||||
setup_logging(verbosity=args.verbose)
|
||||
|
||||
with trezor.Client(factory=trezor.TrezorLibrary) as client:
|
||||
|
||||
label = args.identity
|
||||
@@ -110,3 +113,17 @@ def trezor_agent():
|
||||
use_shell=use_shell)
|
||||
except KeyboardInterrupt:
|
||||
log.info('server stopped')
|
||||
|
||||
|
||||
def trezor_verify():
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('-v', '--verbose', default=0, action='count')
|
||||
p.add_argument('-a', '--address', default=None)
|
||||
p.add_argument('identity')
|
||||
args = p.parse_args()
|
||||
|
||||
setup_logging(verbosity=args.verbose)
|
||||
with trezor.Client(factory=trezor.TrezorLibrary) as client:
|
||||
client.sign_identity(identity=args.identity,
|
||||
expected_address=args.address)
|
||||
|
||||
@@ -2,6 +2,8 @@ import io
|
||||
import re
|
||||
import struct
|
||||
import binascii
|
||||
import time
|
||||
import os
|
||||
|
||||
from . import util
|
||||
from . import formats
|
||||
@@ -88,6 +90,38 @@ class Client(object):
|
||||
s = util.bytes2num(sig[32:])
|
||||
return (r, s)
|
||||
|
||||
def sign_identity(self, identity, expected_address=None):
|
||||
visual = time.strftime('%d/%m/%y %H:%M:%S')
|
||||
hidden = os.urandom(64)
|
||||
identity = self.get_identity(identity)
|
||||
result = self.client.sign_identity(identity=identity,
|
||||
challenge_hidden=hidden,
|
||||
challenge_visual=visual)
|
||||
|
||||
msg = sha256sum(hidden) + sha256sum(visual)
|
||||
sig = result.signature[1:]
|
||||
log.debug('verifying signature for address %s', result.address)
|
||||
if expected_address:
|
||||
assert expected_address == result.address
|
||||
|
||||
curve = formats.ecdsa.SECP256k1
|
||||
verifying_key = formats.decompress_pubkey(result.public_key,
|
||||
curve=curve)
|
||||
|
||||
from bitcoin import electrum_sig_hash
|
||||
from bitcoin import pubkey_to_address
|
||||
assert pubkey_to_address(result.public_key) == result.address
|
||||
|
||||
digest = electrum_sig_hash(msg)
|
||||
r = util.bytes2num(sig[:32])
|
||||
s = util.bytes2num(sig[32:])
|
||||
verifying_key.verify_digest(signature=(r, s), digest=digest,
|
||||
sigdecode=lambda sig, _: sig)
|
||||
|
||||
|
||||
def sha256sum(data):
|
||||
return formats.hashfunc(data).digest()
|
||||
|
||||
|
||||
_identity_regexp = re.compile(''.join([
|
||||
'^'
|
||||
|
||||
Reference in New Issue
Block a user