signer: refactor a bit

This commit is contained in:
Roman Zeyde
2016-04-18 22:10:00 +03:00
parent b2d078eec6
commit 96592269b6

View File

@@ -9,8 +9,6 @@ import struct
import subprocess import subprocess
import time import time
import ecdsa
import decode import decode
import trezor_agent.client import trezor_agent.client
import trezor_agent.formats import trezor_agent.formats
@@ -75,18 +73,18 @@ def hexlify(blob):
class Signer(object): class Signer(object):
curve = ecdsa.NIST256p
ecdsa_curve_name = trezor_agent.formats.CURVE_NIST256 ecdsa_curve_name = trezor_agent.formats.CURVE_NIST256
def __init__(self, user_id, created): def __init__(self, user_id, created):
self.user_id = user_id self.user_id = user_id
self.client_wrapper = trezor_agent.factory.load() self.client_wrapper = trezor_agent.factory.load()
# This requires the following patch to trezor-mcu to work: # This requires the following patch to trezor-mcu in order to work:
# https://gist.github.com/romanz/b66f5df1ca8ef15641df8ea5bb09fd47 # https://gist.github.com/romanz/b66f5df1ca8ef15641df8ea5bb09fd47
self.identity = self.client_wrapper.identity_type() self.identity = self.client_wrapper.identity_type()
self.identity.proto = 'gpg' self.identity.proto = 'gpg'
self.identity.host = user_id self.identity.host = user_id
addr = trezor_agent.client.get_address(self.identity) addr = trezor_agent.client.get_address(self.identity)
public_node = self.client_wrapper.connection.get_public_node( public_node = self.client_wrapper.connection.get_public_node(
n=addr, ecdsa_curve_name=self.ecdsa_curve_name) n=addr, ecdsa_curve_name=self.ecdsa_curve_name)
@@ -96,36 +94,41 @@ class Signer(object):
curve_name=self.ecdsa_curve_name) curve_name=self.ecdsa_curve_name)
self.created = int(created) self.created = int(created)
self.pubkey_point = verifying_key.pubkey.point
log.info('key %s created at %s',
hexlify(self._fingerprint()[-4:]), time_format(self.created))
def _pubkey_data(self):
header = struct.pack('>BLB', header = struct.pack('>BLB',
4, # version 4, # version
self.created, # creation self.created, # creation
19) # ECDSA 19) # ECDSA
# https://tools.ietf.org/html/rfc6637#section-11 (NIST P-256 OID) # https://tools.ietf.org/html/rfc6637#section-11 (NIST P-256 OID)
oid = prefix_len('>B', b'\x2A\x86\x48\xCE\x3D\x03\x01\x07') oid = prefix_len('>B', b'\x2A\x86\x48\xCE\x3D\x03\x01\x07')
return header + oid + mpi((4 << 512) |
(self.pubkey_point.x() << 256) |
(self.pubkey_point.y()))
self._point = verifying_key.pubkey.point def _pubkey_data_to_hash(self):
self.pubkey_data = header + oid + mpi((4 << 512) | return b'\x99' + prefix_len('>H', self._pubkey_data())
(self._point.x() << 256) |
(self._point.y()))
self.data_to_hash = b'\x99' + prefix_len('>H', self.pubkey_data) def _fingerprint(self):
fingerprint = hashlib.sha1(self.data_to_hash).digest() return hashlib.sha1(self._pubkey_data_to_hash()).digest()
self.key_id = fingerprint[-8:]
log.info('key %s created at %s', def key_id(self):
hexlify(fingerprint[-4:]), time_format(self.created)) return self._fingerprint()[-8:]
def close(self): def close(self):
self.client_wrapper.connection.clear_session() self.client_wrapper.connection.clear_session()
self.client_wrapper.connection.close() self.client_wrapper.connection.close()
def export(self): def export(self):
pubkey_packet = packet(tag=6, blob=self.pubkey_data) pubkey_packet = packet(tag=6, blob=self._pubkey_data())
user_id_packet = packet(tag=13, blob=self.user_id) user_id_packet = packet(tag=13, blob=self.user_id)
user_id_to_hash = user_id_packet[:1] + prefix_len('>L', self.user_id) user_id_to_hash = user_id_packet[:1] + prefix_len('>L', self.user_id)
data_to_sign = self.data_to_hash + user_id_to_hash data_to_sign = self._pubkey_data_to_hash() + user_id_to_hash
key_id = hexlify(self.key_id[-4:]) key_id = hexlify(self.key_id()[-4:])
log.info('signing public key "%s": %s', self.user_id, key_id) log.info('signing public key "%s": %s', self.user_id, key_id)
hashed_subpackets = [ hashed_subpackets = [
subpacket_time(self.created), # signature creaion time subpacket_time(self.created), # signature creaion time
@@ -148,7 +151,7 @@ class Signer(object):
log.info('signing message %r at %s', msg, log.info('signing message %r at %s', msg,
time_format(sign_time)) time_format(sign_time))
hashed_subpackets = [subpacket_time(sign_time)] hashed_subpackets = [subpacket_time(sign_time)]
key_id = hexlify(self.key_id[-4:]) key_id = hexlify(self.key_id()[-4:])
blob = self._make_signature( blob = self._make_signature(
visual=key_id, visual=key_id,
data_to_sign=msg, hashed_subpackets=hashed_subpackets) data_to_sign=msg, hashed_subpackets=hashed_subpackets)
@@ -163,7 +166,7 @@ class Signer(object):
8) # hash_alg (SHA256) 8) # hash_alg (SHA256)
hashed = subpackets(*hashed_subpackets) hashed = subpackets(*hashed_subpackets)
unhashed = subpackets( unhashed = subpackets(
subpacket(16, self.key_id) # issuer key id subpacket(16, self.key_id()) # issuer key id
) )
tail = b'\x04\xff' + struct.pack('>L', len(header) + len(hashed)) tail = b'\x04\xff' + struct.pack('>L', len(header) + len(hashed))
data_to_hash = data_to_sign + header + hashed + tail data_to_hash = data_to_sign + header + hashed + tail
@@ -180,7 +183,8 @@ class Signer(object):
sig = result.signature[1:] sig = result.signature[1:]
sig = [trezor_agent.util.bytes2num(sig[:32]), sig = [trezor_agent.util.bytes2num(sig[:32]),
trezor_agent.util.bytes2num(sig[32:])] trezor_agent.util.bytes2num(sig[32:])]
decode.verify_digest(pubkey={'point': (self._point.x(), self._point.y())}, decode.verify_digest(pubkey={'point': (self.pubkey_point.x(),
self.pubkey_point.y())},
digest=digest, digest=digest,
signature=sig, label='GPG signature') signature=sig, label='GPG signature')
@@ -233,7 +237,7 @@ def main():
else: else:
pubkey = load_from_gpg(args.user_id) pubkey = load_from_gpg(args.user_id)
s = Signer(user_id=user_id, created=pubkey['created']) s = Signer(user_id=user_id, created=pubkey['created'])
assert s.key_id == pubkey['key_id'] assert s.key_id() == pubkey['key_id']
data = open(args.filename, 'rb').read() data = open(args.filename, 'rb').read()
sig, ext = s.sign(data), '.sig' sig, ext = s.sign(data), '.sig'