3 import functools as _functools
4 import xml.etree.ElementTree as _etree
6 from . import LOG as _LOG
7 from . import crypt as _crypt
11 from pyassuan import common as _common
14 @_functools.total_ordering
15 class SubKey (object):
16 """The crypographic key portion of an OpenPGP key.
18 def __init__(self, fingerprint=None):
19 self.fingerprint = fingerprint
22 return '<{} {}>'.format(type(self).__name__, self.fingerprint[-8:])
27 def __eq__(self, other):
28 if self.fingerprint and hasattr(other, 'fingerprint'):
29 return self.fingerprint == other.fingerprint
30 return id(self) == id(other)
32 def __lt__(self, other):
33 if self.fingerprint and hasattr(other, 'fingerprint'):
34 return self.fingerprint < other.fingerprint
35 return id(self) < id(other)
38 return int(self.fingerprint, 16)
41 @_functools.total_ordering
42 class UserID (object):
43 def __init__(self, uid=None, name=None, email=None, comment=None):
47 self.comment = comment
50 return '<{} {}>'.format(type(self).__name__, self.name)
55 def __eq__(self, other):
56 if self.uid and hasattr(other, 'uid'):
57 return self.uid == other.uid
58 return id(self) == id(other)
60 def __lt__(self, other):
61 if self.uid and hasattr(other, 'uid'):
62 return self.uid < other.uid
63 return id(self) < id(other)
69 @_functools.total_ordering
71 def __init__(self, subkeys=None, uids=None):
79 can_authenticate = False
88 self.subkeys = subkeys
94 return '<{} {}>'.format(
95 type(self).__name__, self.subkeys[0].fingerprint[-8:])
100 def __eq__(self, other):
101 other_subkeys = getattr(other, 'subkeys', None)
102 if self.subkeys and other_subkeys:
103 return self.subkeys[0] == other.subkeys[0]
104 return id(self) == id(other)
106 def __lt__(self, other):
107 other_subkeys = getattr(other, 'subkeys', None)
108 if self.subkeys and other_subkeys:
109 return self.subkeys[0] < other.subkeys[0]
110 return id(self) < id(other)
113 return int(self.fingerprint, 16)
116 def lookup_keys(patterns=None, **kwargs):
117 """Lookup keys matching any patterns listed in ``patterns``.
121 >>> key = list(lookup_keys(['pgp-mime-test']))[0]
125 [<SubKey 4332B6E3>, <SubKey 2F73DE2E>]
127 [<UserID pgp-mime-test>]
129 'pgp-mime-test (http://blog.tremily.us/posts/pgp-mime/) <pgp-mime@invalid.com>'
135 >>> print(list(lookup_keys(['pgp-mime-test'])))
137 >>> print(list(lookup_keys(['pgp-mime@invalid.com'])))
139 >>> print(list(lookup_keys(['4332B6E3'])))
141 >>> print(list(lookup_keys(['0x2F73DE2E'])))
143 >>> print(list(lookup_keys())) # doctest: +ELLIPSIS
144 [..., <Key 4332B6E3>, ...]
146 _LOG.debug('lookup key: {}'.format(patterns))
147 client = _crypt.get_client(**kwargs)
150 args = [' '.join(patterns)]
155 rs,result = client.make_request(_common.Request('KEYLIST', *args))
157 _crypt.disconnect(client)
160 tree = _etree.fromstring(result.replace(b'\x00', b''))
161 for key in tree.findall('.//key'):
164 attribute = tag_mapping.get(
165 child.tag, child.tag.replace('-', '_'))
167 'revoked', 'expired', 'disabled', 'invalid', 'can-encrypt',
168 'can-sign', 'can-certify', 'can-authenticate', 'is-qualified',
169 'secret', 'revoked']:
171 value = child.get('value')
172 if not value.startswith('0x'):
173 raise NotImplementedError('{} value {}'.format(
175 value = int(value, 16)
178 'protocol', 'owner-trust']:
180 elif child.tag in ['issuer', 'chain-id']:
183 elif child.tag in ['subkeys', 'uids']:
184 parser = globals()['_parse_{}'.format(attribute)]
185 value = parser(child)
187 raise NotImplementedError(child.tag)
188 setattr(k, attribute, value)
191 def _parse_subkeys(element):
193 'fpr': 'fingerprint',
196 for subkey in element:
198 for child in subkey.iter():
199 if child == subkey: # iter() includes the root element
201 attribute = tag_mapping.get(
202 child.tag, child.tag.replace('-', '_'))
207 raise NotImplementedError(child.tag)
208 setattr(s, attribute, value)
212 def _parse_uids(element):
218 for child in uid.iter():
219 if child == uid: # iter() includes the root element
221 attribute = tag_mapping.get(
222 child.tag, child.tag.replace('-', '_'))
224 'uid', 'name', 'email', 'comment']:
227 raise NotImplementedError(child.tag)
228 setattr(u, attribute, value)