From 6fa8b2a9e7f02c59f794e9dd080fac574841e50b Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Fri, 19 Dec 2014 22:37:40 -0600 Subject: upgrade key when signed by old key --- src/leap/keymanager/openpgp.py | 99 ++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 38 deletions(-) (limited to 'src/leap/keymanager/openpgp.py') diff --git a/src/leap/keymanager/openpgp.py b/src/leap/keymanager/openpgp.py index 0adfc52..794a0ec 100644 --- a/src/leap/keymanager/openpgp.py +++ b/src/leap/keymanager/openpgp.py @@ -163,39 +163,6 @@ class TempGPGWrapper(object): shutil.rmtree(self._gpg.homedir) -def _build_key_from_gpg(key, key_data): - """ - Build an OpenPGPKey based on C{key} from local gpg storage. - - ASCII armored GPG key data has to be queried independently in this - wrapper, so we receive it in C{key_data}. - - :param key: Key obtained from GPG storage. - :type key: dict - :param key_data: Key data obtained from GPG storage. - :type key_data: str - :return: An instance of the key. - :rtype: OpenPGPKey - """ - expiry_date = None - if key['expires']: - expiry_date = datetime.fromtimestamp(int(key['expires'])) - address = [] - for uid in key['uids']: - address.append(_parse_address(uid)) - - return OpenPGPKey( - address, - key_id=key['keyid'], - fingerprint=key['fingerprint'], - key_data=key_data, - private=True if key['type'] == 'sec' else False, - length=int(key['length']), - expiry_date=expiry_date, - refreshed_at=datetime.now(), - ) - - def _parse_address(address): """ Remove name, '<', '>' and the identity suffix after the '+' until the '@' @@ -221,6 +188,26 @@ class OpenPGPKey(EncryptionKey): Base class for OpenPGP keys. """ + def __init__(self, address, gpgbinary=None, **kwargs): + self._gpgbinary = gpgbinary + super(OpenPGPKey, self).__init__(address, **kwargs) + + @property + def signatures(self): + """ + Get the key signatures + + :return: the key IDs that have signed the key + :rtype: list(str) + """ + with TempGPGWrapper(keys=[self], gpgbinary=self._gpgbinary) as gpg: + res = gpg.list_sigs(self.key_id) + for uid, sigs in res.sigs.iteritems(): + if _parse_address(uid) in self.address: + return sigs + + return [] + class OpenPGPScheme(EncryptionScheme): """ @@ -298,7 +285,7 @@ class OpenPGPScheme(EncryptionScheme): deferreds = [] for secret in [True, False]: key = gpg.list_keys(secret=secret).pop() - openpgp_key = _build_key_from_gpg( + openpgp_key = self._build_key_from_gpg( key, gpg.export_keys(key['fingerprint'], secret=secret)) d = self.put_key(openpgp_key, address) @@ -335,7 +322,9 @@ class OpenPGPScheme(EncryptionScheme): leap_assert( address in doc.content[KEY_ADDRESS_KEY], 'Wrong address in key data.') - return build_key_from_dict(OpenPGPKey, doc.content) + key = build_key_from_dict(OpenPGPKey, doc.content) + key._gpgbinary = self._gpgbinary + return key d = self._get_key_doc(address, private) d.addCallback(build_key) @@ -375,7 +364,7 @@ class OpenPGPScheme(EncryptionScheme): openpgp_privkey = None if privkey is not None: # build private key - openpgp_privkey = _build_key_from_gpg( + openpgp_privkey = self._build_key_from_gpg( privkey, gpg.export_keys(privkey['fingerprint'], secret=True)) leap_check(pubkey['fingerprint'] == privkey['fingerprint'], @@ -383,7 +372,7 @@ class OpenPGPScheme(EncryptionScheme): errors.KeyFingerprintMismatch) # build public key - openpgp_pubkey = _build_key_from_gpg( + openpgp_pubkey = self._build_key_from_gpg( pubkey, gpg.export_keys(pubkey['fingerprint'], secret=False)) @@ -452,7 +441,7 @@ class OpenPGPScheme(EncryptionScheme): gpg.import_keys(oldkey.key_data) gpg.import_keys(key.key_data) gpgkey = gpg.list_keys(secret=key.private).pop() - mergedkey = _build_key_from_gpg( + mergedkey = self._build_key_from_gpg( gpgkey, gpg.export_keys(gpgkey['fingerprint'], secret=key.private)) @@ -571,6 +560,40 @@ class OpenPGPScheme(EncryptionScheme): d.addCallback(get_key_from_active_doc) return d + def _build_key_from_gpg(self, key, key_data): + """ + Build an OpenPGPKey for C{address} based on C{key} from + local gpg storage. + + ASCII armored GPG key data has to be queried independently in this + wrapper, so we receive it in C{key_data}. + + :param key: Key obtained from GPG storage. + :type key: dict + :param key_data: Key data obtained from GPG storage. + :type key_data: str + :return: An instance of the key. + :rtype: OpenPGPKey + """ + expiry_date = None + if key['expires']: + expiry_date = datetime.fromtimestamp(int(key['expires'])) + address = [] + for uid in key['uids']: + address.append(_parse_address(uid)) + + return OpenPGPKey( + address, + gpgbinary=self._gpgbinary, + key_id=key['keyid'], + fingerprint=key['fingerprint'], + key_data=key_data, + private=True if key['type'] == 'sec' else False, + length=int(key['length']), + expiry_date=expiry_date, + refreshed_at=datetime.now(), + ) + def delete_key(self, key): """ Remove C{key} from storage. -- cgit v1.2.3