mirror of
https://github.com/romanz/amodem.git
synced 2026-04-21 05:36:42 +08:00
gpg: use new device package (instead of factory)
This commit is contained in:
@@ -29,10 +29,10 @@ def run_create(args):
|
|||||||
log.warning('NOTE: in order to re-generate the exact same GPG key later, '
|
log.warning('NOTE: in order to re-generate the exact same GPG key later, '
|
||||||
'run this command with "--time=%d" commandline flag (to set '
|
'run this command with "--time=%d" commandline flag (to set '
|
||||||
'the timestamp of the GPG key manually).', args.time)
|
'the timestamp of the GPG key manually).', args.time)
|
||||||
conn = device.HardwareSigner(user_id=args.user_id,
|
d = device.HardwareSigner(user_id=args.user_id,
|
||||||
curve_name=args.ecdsa_curve)
|
curve_name=args.ecdsa_curve)
|
||||||
verifying_key = conn.pubkey(ecdh=False)
|
verifying_key = d.pubkey(ecdh=False)
|
||||||
decryption_key = conn.pubkey(ecdh=True)
|
decryption_key = d.pubkey(ecdh=True)
|
||||||
|
|
||||||
if key_exists(args.user_id): # add as subkey
|
if key_exists(args.user_id): # add as subkey
|
||||||
log.info('adding %s GPG subkey for "%s" to existing key',
|
log.info('adding %s GPG subkey for "%s" to existing key',
|
||||||
@@ -48,10 +48,10 @@ def run_create(args):
|
|||||||
primary_bytes = keyring.export_public_key(args.user_id)
|
primary_bytes = keyring.export_public_key(args.user_id)
|
||||||
result = encode.create_subkey(primary_bytes=primary_bytes,
|
result = encode.create_subkey(primary_bytes=primary_bytes,
|
||||||
subkey=signing_key,
|
subkey=signing_key,
|
||||||
signer_func=conn.sign)
|
signer_func=d.sign)
|
||||||
result = encode.create_subkey(primary_bytes=result,
|
result = encode.create_subkey(primary_bytes=result,
|
||||||
subkey=encryption_key,
|
subkey=encryption_key,
|
||||||
signer_func=conn.sign)
|
signer_func=d.sign)
|
||||||
else: # add as primary
|
else: # add as primary
|
||||||
log.info('creating new %s GPG primary key for "%s"',
|
log.info('creating new %s GPG primary key for "%s"',
|
||||||
args.ecdsa_curve, args.user_id)
|
args.ecdsa_curve, args.user_id)
|
||||||
@@ -66,10 +66,10 @@ def run_create(args):
|
|||||||
|
|
||||||
result = encode.create_primary(user_id=args.user_id,
|
result = encode.create_primary(user_id=args.user_id,
|
||||||
pubkey=primary,
|
pubkey=primary,
|
||||||
signer_func=conn.sign)
|
signer_func=d.sign)
|
||||||
result = encode.create_subkey(primary_bytes=result,
|
result = encode.create_subkey(primary_bytes=result,
|
||||||
subkey=subkey,
|
subkey=subkey,
|
||||||
signer_func=conn.sign)
|
signer_func=d.sign)
|
||||||
|
|
||||||
sys.stdout.write(protocol.armor(result, 'PUBLIC KEY BLOCK'))
|
sys.stdout.write(protocol.armor(result, 'PUBLIC KEY BLOCK'))
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"""GPG-agent utilities."""
|
"""GPG-agent utilities."""
|
||||||
import binascii
|
import binascii
|
||||||
import contextlib
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from . import decode, device, keyring, protocol
|
from . import decode, device, keyring, protocol
|
||||||
@@ -37,7 +36,6 @@ def sig_encode(r, s):
|
|||||||
return b'(7:sig-val(5:ecdsa(1:r32:' + r + b')(1:s32:' + s + b')))'
|
return b'(7:sig-val(5:ecdsa(1:r32:' + r + b')(1:s32:' + s + b')))'
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def open_connection(keygrip_bytes):
|
def open_connection(keygrip_bytes):
|
||||||
"""
|
"""
|
||||||
Connect to the device for the specified keygrip.
|
Connect to the device for the specified keygrip.
|
||||||
@@ -54,24 +52,23 @@ def open_connection(keygrip_bytes):
|
|||||||
ecdh = (pubkey_dict['algo'] == protocol.ECDH_ALGO_ID)
|
ecdh = (pubkey_dict['algo'] == protocol.ECDH_ALGO_ID)
|
||||||
|
|
||||||
conn = device.HardwareSigner(user_id, curve_name=curve_name)
|
conn = device.HardwareSigner(user_id, curve_name=curve_name)
|
||||||
with contextlib.closing(conn):
|
pubkey = protocol.PublicKey(
|
||||||
pubkey = protocol.PublicKey(
|
curve_name=curve_name, created=pubkey_dict['created'],
|
||||||
curve_name=curve_name, created=pubkey_dict['created'],
|
verifying_key=conn.pubkey(ecdh=ecdh), ecdh=ecdh)
|
||||||
verifying_key=conn.pubkey(ecdh=ecdh), ecdh=ecdh)
|
assert pubkey.key_id() == pubkey_dict['key_id']
|
||||||
assert pubkey.key_id() == pubkey_dict['key_id']
|
assert pubkey.keygrip == keygrip_bytes
|
||||||
assert pubkey.keygrip == keygrip_bytes
|
return conn
|
||||||
yield conn
|
|
||||||
|
|
||||||
|
|
||||||
def pksign(keygrip, digest, algo):
|
def pksign(keygrip, digest, algo):
|
||||||
"""Sign a message digest using a private EC key."""
|
"""Sign a message digest using a private EC key."""
|
||||||
log.debug('signing %r digest (algo #%s)', digest, algo)
|
log.debug('signing %r digest (algo #%s)', digest, algo)
|
||||||
keygrip_bytes = binascii.unhexlify(keygrip)
|
keygrip_bytes = binascii.unhexlify(keygrip)
|
||||||
with open_connection(keygrip_bytes) as conn:
|
conn = open_connection(keygrip_bytes)
|
||||||
r, s = conn.sign(binascii.unhexlify(digest))
|
r, s = conn.sign(binascii.unhexlify(digest))
|
||||||
result = sig_encode(r, s)
|
result = sig_encode(r, s)
|
||||||
log.debug('result: %r', result)
|
log.debug('result: %r', result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _serialize_point(data):
|
def _serialize_point(data):
|
||||||
@@ -105,8 +102,8 @@ def pkdecrypt(keygrip, conn):
|
|||||||
remote_pubkey = parse_ecdh(line)
|
remote_pubkey = parse_ecdh(line)
|
||||||
|
|
||||||
keygrip_bytes = binascii.unhexlify(keygrip)
|
keygrip_bytes = binascii.unhexlify(keygrip)
|
||||||
with open_connection(keygrip_bytes) as conn:
|
conn = open_connection(keygrip_bytes)
|
||||||
return _serialize_point(conn.ecdh(remote_pubkey))
|
return _serialize_point(conn.ecdh(remote_pubkey))
|
||||||
|
|
||||||
|
|
||||||
def handle_connection(conn):
|
def handle_connection(conn):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from .. import factory, formats, util
|
from .. import device, formats, util
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -12,55 +12,33 @@ class HardwareSigner(object):
|
|||||||
|
|
||||||
def __init__(self, user_id, curve_name):
|
def __init__(self, user_id, curve_name):
|
||||||
"""Connect to the device and retrieve required public key."""
|
"""Connect to the device and retrieve required public key."""
|
||||||
self.client_wrapper = factory.load()
|
self.device = device.detect(identity_str='',
|
||||||
self.identity = self.client_wrapper.identity_type()
|
curve_name=curve_name)
|
||||||
self.identity.proto = 'gpg'
|
self.device.identity_dict['proto'] = 'gpg'
|
||||||
self.identity.host = user_id
|
self.device.identity_dict['host'] = user_id
|
||||||
self.curve_name = curve_name
|
|
||||||
self.user_id = user_id
|
self.user_id = user_id
|
||||||
|
|
||||||
def pubkey(self, ecdh=False):
|
def pubkey(self, ecdh=False):
|
||||||
"""Return public key as VerifyingKey object."""
|
"""Return public key as VerifyingKey object."""
|
||||||
addr = util.get_bip32_address(identity=self.identity, ecdh=ecdh)
|
with self.device:
|
||||||
if ecdh:
|
pubkey = self.device.pubkey(ecdh=ecdh)
|
||||||
curve_name = formats.get_ecdh_curve_name(self.curve_name)
|
|
||||||
else:
|
|
||||||
curve_name = self.curve_name
|
|
||||||
public_node = self.client_wrapper.connection.get_public_node(
|
|
||||||
n=addr, ecdsa_curve_name=curve_name)
|
|
||||||
|
|
||||||
return formats.decompress_pubkey(
|
return formats.decompress_pubkey(
|
||||||
pubkey=public_node.node.public_key,
|
pubkey=pubkey, curve_name=self.device.curve_name)
|
||||||
curve_name=curve_name)
|
|
||||||
|
|
||||||
def sign(self, digest):
|
def sign(self, digest):
|
||||||
"""Sign the digest and return a serialized signature."""
|
"""Sign the digest and return a serialized signature."""
|
||||||
log.info('please confirm GPG signature on %s for "%s"...',
|
log.info('please confirm GPG signature on %s for "%s"...',
|
||||||
self.client_wrapper.device_name, self.user_id)
|
self.device, self.user_id)
|
||||||
if self.curve_name == formats.CURVE_NIST256:
|
if self.device.curve_name == formats.CURVE_NIST256:
|
||||||
digest = digest[:32] # sign the first 256 bits
|
digest = digest[:32] # sign the first 256 bits
|
||||||
log.debug('signing digest: %s', util.hexlify(digest))
|
log.debug('signing digest: %s', util.hexlify(digest))
|
||||||
result = self.client_wrapper.connection.sign_identity(
|
with self.device:
|
||||||
identity=self.identity,
|
sig = self.device.sign(blob=digest)
|
||||||
challenge_hidden=digest,
|
|
||||||
challenge_visual='',
|
|
||||||
ecdsa_curve_name=self.curve_name)
|
|
||||||
assert result.signature[:1] == b'\x00'
|
|
||||||
sig = result.signature[1:]
|
|
||||||
return (util.bytes2num(sig[:32]), util.bytes2num(sig[32:]))
|
return (util.bytes2num(sig[:32]), util.bytes2num(sig[32:]))
|
||||||
|
|
||||||
def ecdh(self, pubkey):
|
def ecdh(self, pubkey):
|
||||||
"""Derive shared secret using ECDH from remote public key."""
|
"""Derive shared secret using ECDH from remote public key."""
|
||||||
log.info('please confirm GPG decryption on %s for "%s"...',
|
log.info('please confirm GPG decryption on %s for "%s"...',
|
||||||
self.client_wrapper.device_name, self.user_id)
|
self.device, self.user_id)
|
||||||
result = self.client_wrapper.connection.get_ecdh_session_key(
|
with self.device:
|
||||||
identity=self.identity,
|
return self.device.ecdh(pubkey=pubkey)
|
||||||
peer_public_key=pubkey,
|
|
||||||
ecdsa_curve_name=formats.get_ecdh_curve_name(self.curve_name))
|
|
||||||
assert len(result.session_key) in {65, 33} # NIST256 or Curve25519
|
|
||||||
assert result.session_key[:1] == b'\x04'
|
|
||||||
return result.session_key
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
"""Close the connection to the device."""
|
|
||||||
self.client_wrapper.connection.close()
|
|
||||||
|
|||||||
Reference in New Issue
Block a user