[PATCH gpgme] Add RFC 9980 post-quantum public-key algorithms
Stavros Kousidis
stavros.kousidis at th-koeln.de
Wed Sep 23 15:24:47 CEST 2026
Hi,
I was a bit too quick in promising that I would adapt the patch to this
model.
I understand the motivation to keep GPGME’s existing family/parameter
abstraction. One concern I have, though, is that the newer OpenPGP
composite algorithm identifiers have different semantics from RSA,
ECDSA, or ECDH.
For the latter, the algorithm identifier denotes a family and parameters
such as curve or key size complete the definition. For the RFC 9980
composites, the OpenPGP algorithm identifier itself already denotes the
complete construction, e.g. ML-KEM-768+X25519.
Mapping that back to |GPGME_PK_MLKEM| plus auxiliary parameters
therefore decomposes a protocol-defined algorithm and requires
applications to reconstruct its identity afterwards. I think that is
problematic, especially because there is no longer an unambiguous |bits|
value: in a construction such as ML-KEM-768+X25519 there are two
cryptographic components, and |768| is a parameter-set designation, not
a key length or security strength in bits.
Reconstructing the concrete algorithm from a generic family plus |curve|
and |length| therefore looks to me like a fruitful source of mismatches.
I strongly think this should not be pursued, and that the
protocol-defined composite algorithm should remain represented as such
rather than being decomposed and reconstructed later.
Best
Stavros
On 9/23/26 11:46 AM, Stavros Kousidis wrote:
> Hello,
>
> Thanks, understood. My original patch followed the OpenPGP protocol
> view and exposed the concrete RFC 9980 combinations directly, but I
> see that this does not fit GPGME’s existing abstraction.
>
> I’ll rework the patch so that the OpenPGP algorithm numbers are
> normalized in |_gpgme_map_pk_algo| to generic algorithm families:
>
> * RFC 9980 ML-KEM combinations → |GPGME_PK_MLKEM|, corresponding to
> the proposed |GCRY_PK_MLKEM| pseudo ID 331.
> * RFC 9980 ML-DSA combinations → |GPGME_PK_MLDSA|, corresponding to
> |GCRY_PK_MLDSA| 332.
>
> The concrete OpenPGP combination can then continue to be distinguished
> through the existing curve/key-length metadata, which also keeps RFC
> 9980 distinguishable from the NIST/Brainpool composite draft.
>
> I’ll also align the GnuPG-facing names with the existing GnuPG naming
> conventions.
>
> One question before I send v2: how would you like the RFC 9980 SLH-DSA
> algorithm IDs 32–34 represented? Should there be a generic
> |GPGME_PK_SLHDSA| pseudo identifier, analogous to ML-KEM and ML-DSA,
> or should those remain unmapped for now?
>
> Best
> Stavros
>
>
> On 9/23/26 11:14 AM, Werner Koch wrote:
>> Hello!
>>
>> thanks for working with GPGME and for your patch.
>>
>> I see two problems with your implementation:
>>
>> 1. The name of the identifiers do not match those used by GnuPG. For
>> example GPGME_PK_MLKEM768_X25519 vs PUBKEY_ALGO_MLK768_25519 in
>> GnuPG. This is of course easy to fix by using
>> GPGME_PK_MLK768_25519.
>>
>> Also for "ML-KEM-768+X25519" vs. "mlk768". For the new Brainpool
>> support we use "mlk768_bp384".
>>
>> 2. A combinatorial explosion due to the way RFC-9850 work. In gpgme we
>> should avoid this. For example there is an internal mapping
>>
>> int
>> _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
>> {
>> if (protocol == GPGME_PROTOCOL_OPENPGP)
>> {
>> switch (algo)
>> {
>> case 1: case 2: case 3: case 8: case 16: case 17: break;
>> case 18: algo = GPGME_PK_ECDH; break;
>> case 19: algo = GPGME_PK_ECDSA; break;
>> case 20: break;
>> case 22: algo = GPGME_PK_EDDSA; break;
>> default: algo = 0; break; /* Unknown. */
>> }
>> }
>>
>> used to map the OpenPGP algorithm numbers to to those used by
>> Libgcrypt. This is actually straighforward but in Libgcrypt we do
>> not have separate Ids for each ML-KEM/ECDH combination. Instead we
>> use one identifier (8 for ML-KEM with ECDH) and use the length and
>> curve parameter to specify the details. This reflects what we have
>> always done with RSA, Elgamal, and ECC: A base algorithm and
>> parameters for the details.
>>
>> For the 9980 algos I would suggest to map all ML-KEM algos to a new
>> GPGME_PK_MLKEM which will match a new GCRY_PK_MLKEM Peseudo ID with
>> value 331. For the ML-DSA algos a GPGME_PK_MLDSA would match the
>> Libgcrypt GCRY_PK_MLDSA identifier (value 332). Using these new
>> identifiers we can keep the IETF way of combining the algos apart
>> from your and the BSIs original key combiner (as specified by
>> LibrePGP). They are already denoted by GPGME_PK_KYBER and
>> (eventually) GPGME_PK_DILITHIUM.
>>
>> GPGME applications already need to take the curve (and length)
>> parameter in account and thus can decide whether the 9980 or the
>> LibrePGP key combiner is used.
>>
>>
>> BTW, GnuPG 2.5.23 was released yesterday with support for 9980 inclduing
>> Brainpool and NIST versions of ML-KEM.
>>
>>
>>
>> Salam-Shalom,
>>
>> Werner
>>
>>
--
TH Köln E-Mail-Signatur – Prof. Dr. Stavros Kousidis
*Prof. Dr. Stavros Kousidis*
Faculty of Information, Media and Electrical Engineering
Institute of Computer and Communication Technology
www.th-koeln.de/en/person/stavros.kousidis/
<https://www.th-koeln.de/en/person/stavros.kousidis/>
TH Köln - University of Applied Sciences
Campus Deutz
Betzdorfer Straße 2, 50679 Köln
TH Köln – Technology Arts Sciences
More information about the Gnupg-devel
mailing list