From 7bbf11b63143eaa5be7dc8497a9b899ab8a2be92 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Sat, 11 Jun 2016 14:38:11 +0300 Subject: [PATCH] gpg: refactor key creation --- trezor_agent/gpg/__main__.py | 44 ++++++++++++++++++++++++++++-------- trezor_agent/gpg/encode.py | 18 ++++----------- trezor_agent/gpg/proto.py | 7 +++++- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/trezor_agent/gpg/__main__.py b/trezor_agent/gpg/__main__.py index 7b00cc1..b061b43 100755 --- a/trezor_agent/gpg/__main__.py +++ b/trezor_agent/gpg/__main__.py @@ -16,15 +16,42 @@ log = logging.getLogger(__name__) def run_create(args): """Generate a new pubkey for a new/existing GPG identity.""" user_id = os.environ['TREZOR_GPG_USER_ID'] - f = encode.Factory(user_id=user_id, created=args.time, - curve_name=args.ecdsa_curve, ecdh=args.ecdh) + conn = encode.HardwareSigner(user_id=user_id, + curve_name=args.ecdsa_curve) + verifying_key = conn.pubkey() - with contextlib.closing(f): - if args.subkey: - primary_key = keyring.export_public_key(user_id=user_id) - result = f.create_subkey(primary_bytes=primary_key) - else: - result = f.create_primary() + if args.subkey: + primary_bytes = keyring.export_public_key(user_id=user_id) + # subkey for signing + signing_key = proto.PublicKey( + curve_name=args.ecdsa_curve, created=args.time, + verifying_key=verifying_key, ecdh=False) + # subkey for encryption + encryption_key = proto.PublicKey( + curve_name=args.ecdsa_curve, created=args.time, + verifying_key=verifying_key, ecdh=True) + result = encode.create_subkey(primary_bytes=primary_bytes, + pubkey=signing_key, + signer_func=conn.sign) + result = encode.create_subkey(primary_bytes=result, + pubkey=encryption_key, + signer_func=conn.sign) + else: + # primary key for signing + primary = proto.PublicKey( + curve_name=args.ecdsa_curve, created=args.time, + verifying_key=verifying_key, ecdh=False) + # subkey for encryption + subkey = proto.PublicKey( + curve_name=args.ecdsa_curve, created=args.time, + verifying_key=verifying_key, ecdh=True) + + result = encode.create_primary(user_id=user_id, + pubkey=primary, + signer_func=conn.sign) + result = encode.create_subkey(primary_bytes=result, + pubkey=subkey, + signer_func=conn.sign) sys.stdout.write(proto.armor(result, 'PUBLIC KEY BLOCK')) @@ -48,7 +75,6 @@ def main(): create_cmd = subparsers.add_parser('create') create_cmd.add_argument('-s', '--subkey', action='store_true', default=False) - create_cmd.add_argument('--ecdh', action='store_true', default=False) create_cmd.add_argument('-e', '--ecdsa-curve', default='nist256p1') create_cmd.add_argument('-t', '--time', type=int, default=int(time.time())) create_cmd.set_defaults(run=run_create) diff --git a/trezor_agent/gpg/encode.py b/trezor_agent/gpg/encode.py index 9b5345f..91b6f5a 100644 --- a/trezor_agent/gpg/encode.py +++ b/trezor_agent/gpg/encode.py @@ -119,7 +119,7 @@ def create_primary(user_id, pubkey, signer_func): return pubkey_packet + user_id_packet + sign_packet -def create_subkey(primary_bytes, pubkey, signer_func, ecdh=False): +def create_subkey(primary_bytes, pubkey, signer_func): """Export new subkey to GPG primary key.""" subkey_packet = proto.packet(tag=14, blob=pubkey.data()) primary = decode.load_public_key(primary_bytes) @@ -127,7 +127,7 @@ def create_subkey(primary_bytes, pubkey, signer_func, ecdh=False): primary['user_id'], util.hexlify(primary['key_id'])) data_to_sign = primary['_to_hash'] + pubkey.data_to_hash() - if ecdh: + if pubkey.ecdh: embedded_sig = None else: # Primary Key Binding Signature @@ -147,8 +147,8 @@ def create_subkey(primary_bytes, pubkey, signer_func, ecdh=False): # Subkey Binding Signature # Key flags: https://tools.ietf.org/html/rfc4880#section-5.2.3.21 - # (certify & sign) (encrypt) - flags = (2) if (not ecdh) else (4 | 8) + # (certify & sign) (encrypt) + flags = (2) if (not pubkey.ecdh) else (4 | 8) hashed_subpackets = [ proto.subpacket_time(pubkey.created), # signature time @@ -223,16 +223,6 @@ class Factory(object): """Close connection and turn off the screen of the device.""" self.conn.close() - def create_primary(self): - """Export new subkey to GPG primary key.""" - return create_primary(user_id=self.user_id, pubkey=self.pubkey, - signer_func=self.conn.sign) - - def create_subkey(self, primary_bytes): - """Export new subkey to GPG primary key.""" - return create_subkey(primary_bytes=primary_bytes, pubkey=self.pubkey, - signer_func=self.conn.sign, ecdh=self.ecdh) - def sign_message(self, msg, sign_time=None): """Sign GPG message at specified time.""" if sign_time is None: diff --git a/trezor_agent/gpg/proto.py b/trezor_agent/gpg/proto.py index 5f40b5b..dfbfaee 100644 --- a/trezor_agent/gpg/proto.py +++ b/trezor_agent/gpg/proto.py @@ -154,6 +154,7 @@ class PublicKey(object): self.curve_info = SUPPORTED_CURVES[curve_name] self.created = int(created) # time since Epoch self.verifying_key = verifying_key + self.ecdh = ecdh if ecdh: self.algo_id = ECDH_ALGO_ID self.ecdh_packet = b'\x03\x01\x08\x07' @@ -161,10 +162,14 @@ class PublicKey(object): self.algo_id = self.curve_info['algo_id'] self.ecdh_packet = b'' - self.keygrip = self.curve_info['keygrip'](verifying_key) hex_key_id = util.hexlify(self.key_id())[-8:] self.desc = 'GPG public key {}/{}'.format(curve_name, hex_key_id) + @property + def keygrip(self): + """Compute GPG2 keygrip.""" + return self.curve_info['keygrip'](self.verifying_key) + def data(self): """Data for packet creation.""" header = struct.pack('>BLB',