diff options
| author | J08nY | 2017-08-07 01:30:15 +0200 |
|---|---|---|
| committer | J08nY | 2017-08-07 01:30:15 +0200 |
| commit | be8e21927d063ee5ddd5fc7376669164f9914ad0 (patch) | |
| tree | 590b3c7a582507869670635270ecdac876280176 /src/mailman_pgp/utils/pgp.py | |
| parent | 21b504db4f63efc5d2fa58c646c82d5d8659eca1 (diff) | |
| parent | 59ec076d04340245101de98633705d312374d9fe (diff) | |
| download | mailman-pgp-be8e21927d063ee5ddd5fc7376669164f9914ad0.tar.gz mailman-pgp-be8e21927d063ee5ddd5fc7376669164f9914ad0.tar.zst mailman-pgp-be8e21927d063ee5ddd5fc7376669164f9914ad0.zip | |
Diffstat (limited to 'src/mailman_pgp/utils/pgp.py')
| -rw-r--r-- | src/mailman_pgp/utils/pgp.py | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/src/mailman_pgp/utils/pgp.py b/src/mailman_pgp/utils/pgp.py index 4251693..a8f06f2 100644 --- a/src/mailman_pgp/utils/pgp.py +++ b/src/mailman_pgp/utils/pgp.py @@ -16,7 +16,11 @@ # this program. If not, see <http://www.gnu.org/licenses/>. """Miscellaneous PGP utilities.""" -from pgpy import PGPKey +from pgpy import PGPKey, PGPSignature +from pgpy.constants import SignatureType +from pgpy.errors import PGPError +from pgpy.packet import Packet, Signature +from pgpy.types import Armorable from public import public @@ -72,3 +76,72 @@ def key_from_file(file): """ key, _ = PGPKey.from_file(file) return key + + +@public +def revoc_from_blob(blob): + """ + Load a key revocation signature from an ASCII-Armored blob. + + :param blob: + :return: + :rtype: pgpy.PGPSignature + """ + dearm = Armorable.ascii_unarmor(blob) + p = Packet(dearm['body']) + + if not isinstance(p, Signature): + raise ValueError('Not a key revocation signature.') + if p.sigtype not in (SignatureType.KeyRevocation, + SignatureType.SubkeyRevocation): + raise ValueError('Not a key revocation.') + + sig = PGPSignature() + sig |= p + return sig + + +@public +def key_usable(key, flags_required): + """ + Check that the `key` has the `flags_required` set of KeyFlags. + + Checks only non-expired, non-revoked key/subkeys. Validates revocations it + can, so not those made with some other designated revocation key. + + :param key: The key to check. + :type key: pgpy.PGPKey + :param flags_required: The set of flags required. + :type flags_required: set + :return: Whether the key has the flags_required. + :rtype: bool + """ + if key.is_expired: + return False + for revoc in key.revocation_signatures: + try: + verified = key.verify(key, revoc) + except PGPError: + continue + if bool(verified): + return False + + usage_flags = key.usage_flags() + for subkey in key.subkeys.values(): + if subkey.is_expired: + continue + + valid = True + for revoc in subkey.revocation_signatures: + try: + verified = key.verify(subkey, revoc) + except PGPError: + continue + if bool(verified): + valid = False + break + + if valid: + usage_flags |= subkey.usage_flags() + + return flags_required.issubset(usage_flags) |
