mirror of
https://github.com/romanz/amodem.git
synced 2026-04-20 21:26:39 +08:00
HACK: create subkey with ECDH support
This commit is contained in:
@@ -16,7 +16,7 @@ def run_create(args):
|
|||||||
"""Generate a new pubkey for a new/existing GPG identity."""
|
"""Generate a new pubkey for a new/existing GPG identity."""
|
||||||
user_id = os.environ['TREZOR_GPG_USER_ID']
|
user_id = os.environ['TREZOR_GPG_USER_ID']
|
||||||
f = encode.Factory(user_id=user_id, created=args.time,
|
f = encode.Factory(user_id=user_id, created=args.time,
|
||||||
curve_name=args.ecdsa_curve)
|
curve_name=args.ecdsa_curve, ecdh=args.ecdh)
|
||||||
|
|
||||||
with contextlib.closing(f):
|
with contextlib.closing(f):
|
||||||
if args.subkey:
|
if args.subkey:
|
||||||
@@ -38,6 +38,7 @@ def main():
|
|||||||
|
|
||||||
create = subparsers.add_parser('create')
|
create = subparsers.add_parser('create')
|
||||||
create.add_argument('-s', '--subkey', action='store_true', default=False)
|
create.add_argument('-s', '--subkey', action='store_true', default=False)
|
||||||
|
create.add_argument('--ecdh', action='store_true', default=False)
|
||||||
create.add_argument('-e', '--ecdsa-curve', default='nist256p1')
|
create.add_argument('-e', '--ecdsa-curve', default='nist256p1')
|
||||||
create.add_argument('-t', '--time', type=int, default=int(time.time()))
|
create.add_argument('-t', '--time', type=int, default=int(time.time()))
|
||||||
create.set_defaults(run=run_create)
|
create.set_defaults(run=run_create)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ def _time_format(t):
|
|||||||
class Factory(object):
|
class Factory(object):
|
||||||
"""Performs GPG signing operations."""
|
"""Performs GPG signing operations."""
|
||||||
|
|
||||||
def __init__(self, user_id, created, curve_name):
|
def __init__(self, user_id, created, curve_name, ecdh=False):
|
||||||
"""Construct and loads a public key from the device."""
|
"""Construct and loads a public key from the device."""
|
||||||
self.user_id = user_id
|
self.user_id = user_id
|
||||||
assert curve_name in formats.SUPPORTED_CURVES
|
assert curve_name in formats.SUPPORTED_CURVES
|
||||||
@@ -79,7 +79,8 @@ class Factory(object):
|
|||||||
self.conn = HardwareSigner(user_id, curve_name=curve_name)
|
self.conn = HardwareSigner(user_id, curve_name=curve_name)
|
||||||
self.pubkey = proto.PublicKey(
|
self.pubkey = proto.PublicKey(
|
||||||
curve_name=curve_name, created=created,
|
curve_name=curve_name, created=created,
|
||||||
verifying_key=self.conn.pubkey())
|
verifying_key=self.conn.pubkey(), ecdh=ecdh)
|
||||||
|
self.ecdh = ecdh
|
||||||
|
|
||||||
log.info('%s created at %s for "%s"',
|
log.info('%s created at %s for "%s"',
|
||||||
self.pubkey, _time_format(self.pubkey.created), user_id)
|
self.pubkey, _time_format(self.pubkey.created), user_id)
|
||||||
@@ -142,28 +143,38 @@ class Factory(object):
|
|||||||
self.user_id, util.hexlify(primary['key_id']))
|
self.user_id, util.hexlify(primary['key_id']))
|
||||||
data_to_sign = primary['_to_hash'] + self.pubkey.data_to_hash()
|
data_to_sign = primary['_to_hash'] + self.pubkey.data_to_hash()
|
||||||
|
|
||||||
# Primary Key Binding Signature
|
if self.ecdh:
|
||||||
hashed_subpackets = [
|
embedded_sig = None
|
||||||
proto.subpacket_time(self.pubkey.created)] # signature time
|
else:
|
||||||
unhashed_subpackets = [
|
# Primary Key Binding Signature
|
||||||
proto.subpacket(16, self.pubkey.key_id())] # issuer key id
|
hashed_subpackets = [
|
||||||
log.info('confirm signing subkey with hardware device')
|
proto.subpacket_time(self.pubkey.created)] # signature time
|
||||||
embedded_sig = proto.make_signature(
|
unhashed_subpackets = [
|
||||||
signer_func=self.conn.sign,
|
proto.subpacket(16, self.pubkey.key_id())] # issuer key id
|
||||||
data_to_sign=data_to_sign,
|
log.info('confirm signing subkey with hardware device')
|
||||||
public_algo=self.pubkey.algo_id,
|
embedded_sig = proto.make_signature(
|
||||||
sig_type=0x19,
|
signer_func=self.conn.sign,
|
||||||
hashed_subpackets=hashed_subpackets,
|
data_to_sign=data_to_sign,
|
||||||
unhashed_subpackets=unhashed_subpackets)
|
public_algo=self.pubkey.algo_id,
|
||||||
|
sig_type=0x19,
|
||||||
|
hashed_subpackets=hashed_subpackets,
|
||||||
|
unhashed_subpackets=unhashed_subpackets)
|
||||||
|
|
||||||
# Subkey Binding Signature
|
# Subkey Binding Signature
|
||||||
|
flags = 2 # key flags (certify & sign)
|
||||||
|
if self.ecdh:
|
||||||
|
flags = 4 | 8
|
||||||
|
|
||||||
hashed_subpackets = [
|
hashed_subpackets = [
|
||||||
proto.subpacket_time(self.pubkey.created), # signature time
|
proto.subpacket_time(self.pubkey.created), # signature time
|
||||||
proto.subpacket_byte(0x1B, 2)] # key flags (certify & sign)
|
proto.subpacket_byte(0x1B, flags)]
|
||||||
unhashed_subpackets = [
|
|
||||||
proto.subpacket(16, primary['key_id']), # issuer key id
|
unhashed_subpackets = []
|
||||||
proto.subpacket(32, embedded_sig),
|
unhashed_subpackets.append(proto.subpacket(16, primary['key_id']))
|
||||||
proto.CUSTOM_SUBPACKET]
|
if embedded_sig is not None:
|
||||||
|
unhashed_subpackets.append(proto.subpacket(32, embedded_sig))
|
||||||
|
unhashed_subpackets.append(proto.CUSTOM_SUBPACKET)
|
||||||
|
|
||||||
log.info('confirm signing subkey with gpg-agent')
|
log.info('confirm signing subkey with gpg-agent')
|
||||||
gpg_agent = AgentSigner(self.user_id)
|
gpg_agent = AgentSigner(self.user_id)
|
||||||
signature = proto.make_signature(
|
signature = proto.make_signature(
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ SUPPORTED_CURVES = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ECDH_ALGO_ID = 18
|
||||||
|
|
||||||
CUSTOM_SUBPACKET = subpacket(100, b'TREZOR-GPG') # marks "our" pubkey
|
CUSTOM_SUBPACKET = subpacket(100, b'TREZOR-GPG') # marks "our" pubkey
|
||||||
|
|
||||||
@@ -145,12 +146,18 @@ def find_curve_by_algo_id(algo_id):
|
|||||||
class PublicKey(object):
|
class PublicKey(object):
|
||||||
"""GPG representation for public key packets."""
|
"""GPG representation for public key packets."""
|
||||||
|
|
||||||
def __init__(self, curve_name, created, verifying_key):
|
def __init__(self, curve_name, created, verifying_key, ecdh=False):
|
||||||
"""Contruct using a ECDSA VerifyingKey object."""
|
"""Contruct using a ECDSA VerifyingKey object."""
|
||||||
self.curve_info = SUPPORTED_CURVES[curve_name]
|
self.curve_info = SUPPORTED_CURVES[curve_name]
|
||||||
self.created = int(created) # time since Epoch
|
self.created = int(created) # time since Epoch
|
||||||
self.verifying_key = verifying_key
|
self.verifying_key = verifying_key
|
||||||
self.algo_id = self.curve_info['algo_id']
|
if ecdh:
|
||||||
|
self.algo_id = ECDH_ALGO_ID
|
||||||
|
self.ecdh_packet = b'\x03\x01\x08\x07'
|
||||||
|
else:
|
||||||
|
self.algo_id = self.curve_info['algo_id']
|
||||||
|
self.ecdh_packet = b''
|
||||||
|
|
||||||
self.keygrip = self.curve_info['keygrip'](verifying_key)
|
self.keygrip = self.curve_info['keygrip'](verifying_key)
|
||||||
hex_key_id = util.hexlify(self.key_id())[-8:]
|
hex_key_id = util.hexlify(self.key_id())[-8:]
|
||||||
self.desc = 'GPG public key {}/{}'.format(curve_name, hex_key_id)
|
self.desc = 'GPG public key {}/{}'.format(curve_name, hex_key_id)
|
||||||
@@ -163,7 +170,7 @@ class PublicKey(object):
|
|||||||
self.algo_id) # public key algorithm ID
|
self.algo_id) # public key algorithm ID
|
||||||
oid = util.prefix_len('>B', self.curve_info['oid'])
|
oid = util.prefix_len('>B', self.curve_info['oid'])
|
||||||
blob = self.curve_info['serialize'](self.verifying_key)
|
blob = self.curve_info['serialize'](self.verifying_key)
|
||||||
return header + oid + blob
|
return header + oid + blob + self.ecdh_packet
|
||||||
|
|
||||||
def data_to_hash(self):
|
def data_to_hash(self):
|
||||||
"""Data for digest computation."""
|
"""Data for digest computation."""
|
||||||
|
|||||||
Reference in New Issue
Block a user