From 8f196909430180f354de52a6a3f05a2798a16550 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Fri, 14 Oct 2016 22:20:28 +0300 Subject: [PATCH] gpg: support Curve25519 for creating encryption subkeys --- trezor_agent/formats.py | 17 +++++++++++++++-- trezor_agent/gpg/__main__.py | 10 +++++----- trezor_agent/gpg/device.py | 10 +++++++--- trezor_agent/gpg/protocol.py | 8 +++++++- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/trezor_agent/formats.py b/trezor_agent/formats.py index de8ec82..5c64410 100644 --- a/trezor_agent/formats.py +++ b/trezor_agent/formats.py @@ -11,11 +11,15 @@ from . import util log = logging.getLogger(__name__) -# Supported ECDSA curves +# Supported ECDSA curves (for SSH and GPG) CURVE_NIST256 = 'nist256p1' CURVE_ED25519 = 'ed25519' SUPPORTED_CURVES = {CURVE_NIST256, CURVE_ED25519} +# Supported ECDH curves (for GPG) +ECDH_NIST256 = 'nist256p1' +ECDH_CURVE25519 = 'curve25519' + # SSH key types SSH_NIST256_DER_OCTET = b'\x04' SSH_NIST256_KEY_PREFIX = b'ecdsa-sha2-' @@ -134,7 +138,8 @@ def decompress_pubkey(pubkey, curve_name): if len(pubkey) == 33: decompress = { CURVE_NIST256: _decompress_nist256, - CURVE_ED25519: _decompress_ed25519 + CURVE_ED25519: _decompress_ed25519, + ECDH_CURVE25519: _decompress_ed25519, }[curve_name] vk = decompress(pubkey) @@ -192,3 +197,11 @@ def import_public_key(line): assert result['type'] == file_type.encode('ascii') log.debug('loaded %s public key: %s', file_type, result['fingerprint']) return result + + +def get_ecdh_curve_name(signature_curve_name): + """Return appropriate curve for ECDH for specified signing curve.""" + return { + CURVE_NIST256: ECDH_NIST256, + CURVE_ED25519: ECDH_CURVE25519, + }[signature_curve_name] diff --git a/trezor_agent/gpg/__main__.py b/trezor_agent/gpg/__main__.py index 6c176a9..648f7be 100755 --- a/trezor_agent/gpg/__main__.py +++ b/trezor_agent/gpg/__main__.py @@ -8,7 +8,7 @@ import sys import time from . import agent, device, encode, keyring, protocol -from .. import server +from .. import formats, server log = logging.getLogger(__name__) @@ -32,8 +32,8 @@ def run_create(args): verifying_key=verifying_key, ecdh=False) # subkey for encryption encryption_key = protocol.PublicKey( - curve_name=args.ecdsa_curve, created=args.time, - verifying_key=decryption_key, ecdh=True) + curve_name=formats.get_ecdh_curve_name(args.ecdsa_curve), + created=args.time, verifying_key=decryption_key, ecdh=True) result = encode.create_subkey(primary_bytes=primary_bytes, pubkey=signing_key, signer_func=conn.sign) @@ -47,8 +47,8 @@ def run_create(args): verifying_key=verifying_key, ecdh=False) # subkey for encryption subkey = protocol.PublicKey( - curve_name=args.ecdsa_curve, created=args.time, - verifying_key=decryption_key, ecdh=True) + curve_name=formats.get_ecdh_curve_name(args.ecdsa_curve), + created=args.time, verifying_key=decryption_key, ecdh=True) result = encode.create_primary(user_id=user_id, pubkey=primary, diff --git a/trezor_agent/gpg/device.py b/trezor_agent/gpg/device.py index a81a27b..6e209b2 100644 --- a/trezor_agent/gpg/device.py +++ b/trezor_agent/gpg/device.py @@ -17,12 +17,16 @@ class HardwareSigner(object): def pubkey(self, ecdh=False): """Return public key as VerifyingKey object.""" addr = util.get_bip32_address(identity=self.identity, ecdh=ecdh) + if 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=self.curve_name) + n=addr, ecdsa_curve_name=curve_name) return formats.decompress_pubkey( pubkey=public_node.node.public_key, - curve_name=self.curve_name) + curve_name=curve_name) def sign(self, digest): """Sign the digest and return a serialized signature.""" @@ -40,7 +44,7 @@ class HardwareSigner(object): result = self.client_wrapper.connection.get_ecdh_session_key( identity=self.identity, peer_public_key=pubkey, - ecdsa_curve_name=self.curve_name) + ecdsa_curve_name=formats.get_ecdh_curve_name(self.curve_name)) assert len(result.session_key) == 65 assert result.session_key[:1] == b'\x04' return result.session_key diff --git a/trezor_agent/gpg/protocol.py b/trezor_agent/gpg/protocol.py index b4d4e01..0c5cc4b 100644 --- a/trezor_agent/gpg/protocol.py +++ b/trezor_agent/gpg/protocol.py @@ -141,7 +141,13 @@ SUPPORTED_CURVES = { 'algo_id': 22, 'serialize': _serialize_ed25519, 'keygrip': _keygrip_ed25519, - } + }, + formats.ECDH_CURVE25519: { + 'oid': b'\x2B\x06\x01\x04\x01\x97\x55\x01\x05\x01', + 'algo_id': 18, + 'serialize': _serialize_ed25519, + 'keygrip': _keygrip_ed25519, + }, } ECDH_ALGO_ID = 18