gpg: refactor client usage at agent module
This allows caching public keys (as done in the SSH agent).
This commit is contained in:
@@ -2,43 +2,47 @@
|
||||
|
||||
import logging
|
||||
|
||||
from .. import device, formats, util
|
||||
from .. import formats, util
|
||||
from ..device import interface
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_identity(user_id, curve_name):
|
||||
"""Create GPG identity for hardware device."""
|
||||
result = interface.Identity(identity_str='gpg://', curve_name=curve_name)
|
||||
result.identity_dict['host'] = user_id
|
||||
return result
|
||||
|
||||
|
||||
class Client(object):
|
||||
"""Sign messages and get public keys from a hardware device."""
|
||||
|
||||
def __init__(self, user_id, curve_name, device_type):
|
||||
"""Connect to the device and retrieve required public key."""
|
||||
self.device = device_type()
|
||||
self.user_id = user_id
|
||||
self.identity = device.interface.Identity(
|
||||
identity_str='gpg://', curve_name=curve_name)
|
||||
self.identity.identity_dict['host'] = user_id
|
||||
def __init__(self, device):
|
||||
"""C-tor."""
|
||||
self.device = device
|
||||
|
||||
def pubkey(self, ecdh=False):
|
||||
def pubkey(self, identity, ecdh=False):
|
||||
"""Return public key as VerifyingKey object."""
|
||||
with self.device:
|
||||
pubkey = self.device.pubkey(ecdh=ecdh, identity=self.identity)
|
||||
pubkey = self.device.pubkey(ecdh=ecdh, identity=identity)
|
||||
return formats.decompress_pubkey(
|
||||
pubkey=pubkey, curve_name=self.identity.curve_name)
|
||||
pubkey=pubkey, curve_name=identity.curve_name)
|
||||
|
||||
def sign(self, digest):
|
||||
def sign(self, identity, digest):
|
||||
"""Sign the digest and return a serialized signature."""
|
||||
log.info('please confirm GPG signature on %s for "%s"...',
|
||||
self.device, self.user_id)
|
||||
if self.identity.curve_name == formats.CURVE_NIST256:
|
||||
self.device, identity)
|
||||
if identity.curve_name == formats.CURVE_NIST256:
|
||||
digest = digest[:32] # sign the first 256 bits
|
||||
log.debug('signing digest: %s', util.hexlify(digest))
|
||||
with self.device:
|
||||
sig = self.device.sign(blob=digest, identity=self.identity)
|
||||
sig = self.device.sign(blob=digest, identity=identity)
|
||||
return (util.bytes2num(sig[:32]), util.bytes2num(sig[32:]))
|
||||
|
||||
def ecdh(self, pubkey):
|
||||
def ecdh(self, identity, pubkey):
|
||||
"""Derive shared secret using ECDH from remote public key."""
|
||||
log.info('please confirm GPG decryption on %s for "%s"...',
|
||||
self.device, self.user_id)
|
||||
self.device, identity)
|
||||
with self.device:
|
||||
return self.device.ecdh(pubkey=pubkey, identity=self.identity)
|
||||
return self.device.ecdh(pubkey=pubkey, identity=identity)
|
||||
|
||||
Reference in New Issue
Block a user