""" GnuPG abstraction layer Copyright (C) 2010-2020 Cr@ns <roots@crans.org> Authors : Daniel Stan <daniel.stan@crans.org> Vincent Le Gallic <legallic@crans.org> Alexandre Iooss <erdnaxe@crans.org> SPDX-License-Identifier: GPL-3.0-or-later """ import subprocess import logging import gpg # Local logger log = logging.getLogger(__name__) def decrypt(ciphertext: str): """ Return decrypted content """ log.info("Decrypting using GnuPG") with gpg.Context() as c: plaintext, _, _ = c.decrypt(ciphertext.encode("utf-8")) return plaintext.decode("utf-8") def encrypt(content: str, keys: []) -> str: """ Return encrypted content for keys """ log.info("Encrypting using GnuPG") with gpg.Context() as c: c.armor = True cipher, _, _ = c.encrypt(content.encode("utf-8"), keys) return cipher.decode("utf-8") def receive_key(fpr: str): """ Download key from fingerprint """ full_command = ['gpg', '--recv-keys', fpr] log.info("Running `%s`" % " ".join(full_command)) return subprocess.run(full_command) def check_key_validity(key, email: str) -> bool: """ Check key identities email and trust level Return true if can be trusted """ log.info("Checking %s key with email %s" % (key.fpr, email)) for uid in key.uids: if email == uid.email and not uid.revoked and not uid.invalid \ and uid.validity >= gpg.constants.validity.FULL: return True # no trusted valid uid were found return False def get_key(fpr): """ Get GnuPG key by fingerprint, ask to download if missing """ # TODO: use --force and ignore-invalid log.info("Getting key corresponding to %s" % fpr) with gpg.Context() as c: try: return c.get_key(fpr) except gpg.errors.KeyNotFound: log.error("key correponding to fingerprint %s not found" % fpr) # ask to download key answer = input("Do you want to try to import it now ? [Y/n] ") if answer.lower() == "y" or answer == "": receive_key(fpr) return get_key(fpr)