commit: 364ea345b5d32ecf24d30ea248daea8f5dc51286 Author: Michał Górny <mgorny <AT> gentoo <DOT> org> AuthorDate: Sat Oct 25 15:41:49 2025 +0000 Commit: Michał Górny <mgorny <AT> gentoo <DOT> org> CommitDate: Sat Oct 25 15:46:48 2025 +0000 URL: https://gitweb.gentoo.org/proj/gemato.git/commit/?id=364ea345
openpgp: Do not require "fpr" to follow "pub" immediately Fix processing "gpg --with-colons --list-keys" output to accept additional data (e.g. "rvk" lines) between a "pub" and a "fpr", as long as no UIDs or subkeys get in the way. Closes: https://github.com/gentoo/gemato/issues/39 Signed-off-by: Michał Górny <mgorny <AT> gentoo.org> gemato/openpgp.py | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/gemato/openpgp.py b/gemato/openpgp.py index a03dba3..155bdef 100644 --- a/gemato/openpgp.py +++ b/gemato/openpgp.py @@ -157,30 +157,41 @@ class SystemGPGEnvironment: fpr = None ret = {} for line in out.splitlines(): - # were we expecting a fingerprint? - if prev_pub is not None: - if line.startswith(b'fpr:'): - fpr = line.split(b':')[9].decode('ASCII') - if not fpr.endswith(prev_pub): - raise OpenPGPKeyListingError( - f'Incorrect fingerprint {fpr} for key ' - f'{prev_pub}') - LOGGER.debug( - f'list_keys(): fingerprint: {fpr}') - ret[fpr] = [] - prev_pub = None - else: + if line.startswith(b"fpr:"): + fpr = line.split(b":")[9].decode("ASCII") + # this can be subkey fingerprint + if prev_pub is None: + continue + if not fpr.endswith(prev_pub): raise OpenPGPKeyListingError( - f'No fingerprint in GPG output, instead got: ' - f'{line}') - elif line.startswith(b'pub:'): + f"Incorrect fingerprint {fpr} for key {prev_pub}" + ) + LOGGER.debug( + f"list_keys(): fingerprint: {fpr}") + ret[fpr] = [] + prev_pub = None + elif line.startswith(b"pub:"): + if prev_pub is not None: + raise OpenPGPKeyListingError( + f"New key while waiting for fingerprint: {line} " + f"({prev_pub=})" + ) # wait for the fingerprint - prev_pub = line.split(b':')[4].decode('ASCII') - LOGGER.debug(f'list_keys(): keyid: {prev_pub}') + prev_pub = line.split(b":")[4].decode("ASCII") + LOGGER.debug(f"list_keys(): keyid: {prev_pub}") + elif line.startswith(b"sub:"): + if fpr is None: + raise OpenPGPKeyListingError( + "Subkey without prior fingerprint in GPG output: " + f"{line} ({prev_pub=})" + ) + prev_pub = None elif line.startswith(b'uid:'): if fpr is None: raise OpenPGPKeyListingError( - f'UID without key in GPG output: {line}') + f"UID without prior fingerprint in GPG output: {line} " + f"({prev_pub=})" + ) uid_split = line.split(b":", 10) uid = uid_split[9] # no creation date means missing/broken self-sig
