From eab8b88fe3f4940a9f8285cfb8b88070cd5c0050 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 20 Sep 2012 12:24:27 -0400 Subject: [PATCH] key: add pgp_mime.key wrapping gpgme-tool's KEYLIST command. This lets you lookup key information. Eventually, you'll be able to look up user IDs, email addresses, subkeys, etc. However, gpgme-tool's XML output for KEYLIST (result_keylist_to_xml) is a stub as of: commit 83e74202cd7c4c975d149c49e2507fdb0e60ef32 Commit: Marcus Brinkmann CommitDate: Sat Jul 28 22:11:31 2012 +0200 Add two recent contributors. --- pgp_mime/crypt.py | 4 ++- pgp_mime/key.py | 87 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 pgp_mime/key.py diff --git a/pgp_mime/crypt.py b/pgp_mime/crypt.py index 883a8a1..8bc4519 100644 --- a/pgp_mime/crypt.py +++ b/pgp_mime/crypt.py @@ -317,7 +317,9 @@ def verify_bytes(data, signature=None, always_trust=False): public key algorithm: RSA hash algorithm: SHA1 - Data signed by a subkey returns the subkey fingerprint. + Data signed by a subkey returns the subkey fingerprint. To find + the primary key for a given subkey, use + ``pgp_mime.key.lookup_keys()``. >>> b = '\n'.join([ ... '-----BEGIN PGP MESSAGE-----', diff --git a/pgp_mime/key.py b/pgp_mime/key.py new file mode 100644 index 0000000..0b5812d --- /dev/null +++ b/pgp_mime/key.py @@ -0,0 +1,87 @@ +# Copyright + +import xml.etree.ElementTree as _etree + +from . import LOG as _LOG +from . import crypt as _crypt + +import pyassuan +import logging +from pyassuan import common as _common + + +class Key (object): + def __init__(self, fingerprint=None): + self.fingerprint = fingerprint + # more data to come once gpgme-tool gets keylist XML support + + def __str__(self): + return '<{} {}>'.format(self.__class__.__name__, self.fingerprint[-8:]) + + def __repr__(self): + return str(self) + + +def lookup_keys(patterns=None, load=False): + """Lookup keys matching any patterns listed in ``patterns``. + + >>> print(list(lookup_keys(['pgp-mime-test']))) + [] + >>> print(list(lookup_keys(['pgp-mime@invalid.com']))) + [] + >>> print(list(lookup_keys(['4332B6E3']))) + [] + >>> print(list(lookup_keys(['0x2F73DE2E']))) + [] + >>> print(list(lookup_keys())) # doctest: +ELLIPSIS + [..., , ...] + + >>> key = lookup_keys(['2F73DE2E'], load=True) + >>> print(list(key)[0]) + Traceback (most recent call last): + ... + NotImplementedError: gpgme-tool doesn't return keylist data + """ + _LOG.debug('lookup key: {}'.format(patterns)) + pyassuan.LOG.setLevel(logging.DEBUG) + client,socket = _crypt.get_client() + parameters = [] + if patterns: + args = [' '.join(patterns)] + else: + args = [] + try: + _crypt.hello(client) + if load: + client.make_request(_common.Request('KEYLIST', *args)) + rs,result = client.make_request(_common.Request('RESULT', *args)) + else: + rs,result = client.make_request(_common.Request('KEYLIST', *args)) + finally: + _crypt.disconnect(client, socket) + if load: + tag_mapping = { + 'fpr': 'fingerprint', + } + tree = _etree.fromstring(result.replace(b'\x00', b'')) + if list(tree.findall('.//truncated')): + raise NotImplementedError("gpgme-tool doesn't return keylist data") + for signature in tree.findall('.//key'): + key = Key() + for child in signature.iter(): + if child == signature: # iter() includes the root element + continue + attribute = tag_mapping.get( + child.tag, child.tag.replace('-', '_')) + if child.tag in ['fpr']: + value = child.text + else: + raise NotImplementedError(child.tag) + setattr(s, attribute, value) + yield key + else: + for line in result.splitlines(): + line = str(line, 'ascii') + assert line.startswith('key:'), result + fingerprint = line.split(':', 1)[1] + yield Key(fingerprint=fingerprint) -- 2.26.2