comparison libervia/backend/plugins/plugin_xep_0373.py @ 4332:71c939e34ca6

XEP-0373 (OX): Adjust to gpgme updates: generate with explicit algorithm and subkeys
author Syndace <me@syndace.dev>
date Sat, 13 Jul 2024 18:28:28 +0200
parents 0d7bb4df2343
children 111dce64dcb5
comparison
equal deleted inserted replaced
4331:e0ae6ca806ba 4332:71c939e34ca6
1 #!/usr/bin/env python3 1 #!/usr/bin/env python3
2 2
3 # Libervia plugin for OpenPGP for XMPP 3 # Libervia plugin for OpenPGP for XMPP
4 # Copyright (C) 2022-2022 Tim Henkes (me@syndace.dev) 4 # Copyright (C) 2022-2024 Tim Henkes (me@syndace.dev)
5 5
6 # This program is free software: you can redistribute it and/or modify 6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as published by 7 # it under the terms of the GNU Affero General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or 8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version. 9 # (at your option) any later version.
441 441
442 class GPGME_GPGProvider(GPGProvider): 442 class GPGME_GPGProvider(GPGProvider):
443 """ 443 """
444 GPG provider implementation based on GnuPG Made Easy (GPGME). 444 GPG provider implementation based on GnuPG Made Easy (GPGME).
445 """ 445 """
446
447 ALGORITHM = "ed25519/cert,sign+cv25519/encr"
446 448
447 def __init__(self, home_dir: Optional[str] = None) -> None: 449 def __init__(self, home_dir: Optional[str] = None) -> None:
448 """ 450 """
449 @param home_dir: Optional GPG home directory path to use for all operations. 451 @param home_dir: Optional GPG home directory path to use for all operations.
450 """ 452 """
775 return any(subkey.can_encrypt for subkey in public_key.key_obj.subkeys) 777 return any(subkey.can_encrypt for subkey in public_key.key_obj.subkeys)
776 778
777 def create_key(self, user_id: str) -> GPGSecretKey: 779 def create_key(self, user_id: str) -> GPGSecretKey:
778 with gpg.Context(home_dir=self.__home_dir) as c: 780 with gpg.Context(home_dir=self.__home_dir) as c:
779 try: 781 try:
780 result = c.create_key( 782 # A single ECC (primary) key with signing and encryption capabilities is not supported, a
783 # subkey is required for encryption.
784 # Create a primary key only capable of certifying subkeys
785 primary_create_result = c.create_key(
781 user_id, 786 user_id,
787 algorithm=self.ALGORITHM,
782 expires=False, 788 expires=False,
783 sign=True, 789 certify=True,
784 encrypt=True, 790 force=True
785 certify=False,
786 authenticate=False,
787 force=True,
788 ) 791 )
789 792
790 key_obj = c.get_key(result.fpr, secret=True) 793 primary_key_obj = c.get_key(primary_create_result.fpr, secret=True)
794
795 c.create_subkey(
796 primary_key_obj,
797 algorithm=self.ALGORITHM,
798 expires=False,
799 sign=True
800 )
801
802 c.create_subkey(
803 primary_key_obj,
804 algorithm=self.ALGORITHM,
805 expires=False,
806 encrypt=True
807 )
791 except gpg.errors.GPGMEError as e: 808 except gpg.errors.GPGMEError as e:
792 raise GPGProviderError("Internal GPGME error") from e 809 raise GPGProviderError("Internal GPGME error") from e
793 except gpg.errors.KeyError as e: 810 except gpg.errors.KeyNotFound as e:
794 raise GPGProviderError("Newly created key not found") from e 811 raise GPGProviderError("Newly created key not found") from e
795 812
796 return GPGME_GPGSecretKey(GPGME_GPGPublicKey(key_obj)) 813 return GPGME_GPGSecretKey(GPGME_GPGPublicKey(primary_key_obj))
797 814
798 815
799 class PublicKeyMetadata(NamedTuple): 816 class PublicKeyMetadata(NamedTuple):
800 """ 817 """
801 Metadata about a published public key. 818 Metadata about a published public key.