diff --git a/gnupg/_parsers.py b/gnupg/_parsers.py index 8e5d751..a99e910 100644 --- a/gnupg/_parsers.py +++ b/gnupg/_parsers.py @@ -959,7 +959,6 @@ class ListKeys(list): | crs = X.509 certificate and private key available | ssb = secret subkey (secondary key) | uat = user attribute (same as user id except for field 10). - | sig = signature | rev = revocation signature | pkd = public key data (special field format, see below) | grp = reserved for gpgsm @@ -970,8 +969,10 @@ class ListKeys(list): super(ListKeys, self).__init__() self._gpg = gpg self.curkey = None + self.curuid = None self.fingerprints = [] self.uids = [] + self.sigs = {} def key(self, args): vars = (""" @@ -981,8 +982,12 @@ class ListKeys(list): for i in range(len(vars)): self.curkey[vars[i]] = args[i] self.curkey['uids'] = [] + self.curkey['sigs'] = {} if self.curkey['uid']: - self.curkey['uids'].append(self.curkey['uid']) + self.curuid = self.curkey['uid'] + self.curkey['uids'].append(self.curuid) + self.sigs[self.curuid] = set() + self.curkey['sigs'][self.curuid] = [] del self.curkey['uid'] self.curkey['subkeys'] = [] self.append(self.curkey) @@ -997,8 +1002,21 @@ class ListKeys(list): uid = args[9] uid = ESCAPE_PATTERN.sub(lambda m: chr(int(m.group(1), 16)), uid) self.curkey['uids'].append(uid) + self.curuid = uid + self.curkey['sigs'][uid] = [] + self.sigs[uid] = set() self.uids.append(uid) + def sig(self, args): + vars = (""" + type trust length algo keyid date expires dummy ownertrust uid + """).split() + sig = {} + for i in range(len(vars)): + sig[vars[i]] = args[i] + self.curkey['sigs'][self.curuid].append(sig) + self.sigs[self.curuid].add(sig['keyid']) + def sub(self, args): subkey = [args[4], args[11]] self.curkey['subkeys'].append(subkey) diff --git a/gnupg/gnupg.py b/gnupg/gnupg.py index 42498db..18a8385 100644 --- a/gnupg/gnupg.py +++ b/gnupg/gnupg.py @@ -471,19 +471,7 @@ class GPG(GPGBase): self._collect_output(p, result, stdin=p.stdin) lines = result.data.decode(self._encoding, self._decode_errors).splitlines() - valid_keywords = 'pub uid sec fpr sub'.split() - for line in lines: - if self.verbose: - print(line) - log.debug("%r", line.rstrip()) - if not line: - break - L = line.strip().split(':') - if not L: - continue - keyword = L[0] - if keyword in valid_keywords: - getattr(result, keyword)(L) + self._parse_keys(result) return result def list_packets(self, raw_data): @@ -504,8 +492,8 @@ class GPG(GPGBase): >>> assert key.fingerprint :rtype: dict - :returns: A dictionary whose keys are the original keyid parameters, - and whose values are lists of signatures. + :returns: res.sigs is a dictionary whose keys are the uids and whose + values are a set of signature keyids. """ if len(keyids) > self._batch_limit: raise ValueError( @@ -520,8 +508,26 @@ class GPG(GPGBase): proc = self._open_subprocess(args) result = self._result_map['list'](self) self._collect_output(proc, result, stdin=proc.stdin) + self._parse_keys(result) return result + def _parse_keys(self, result): + lines = result.data.decode(self._encoding, + self._decode_errors).splitlines() + valid_keywords = 'pub uid sec fpr sub sig'.split() + for line in lines: + if self.verbose: + print(line) + log.debug("%r", line.rstrip()) + if not line: + break + L = line.strip().split(':') + if not L: + continue + keyword = L[0] + if keyword in valid_keywords: + getattr(result, keyword)(L) + def gen_key(self, input): """Generate a GnuPG key through batch file key generation. See :meth:`GPG.gen_key_input()` for creating the control input.