Hybrid keys

A hybrid key combines a post-quantum key with a traditional one: the result stays secure as long as at least one of the two algorithms is secure. It protects against quantum computers (thanks to the post-quantum algorithm) without relying only on an algorithm that is still relatively new (the traditional one is still there, should the post-quantum one fail).

The combination is selected by the param_set argument, one of the members of the enum Crypto.PublicKey.Hybrid.ParamSet (also available as constants at the module level, for instance Hybrid.MLKEM768_X25519). The parameter set also decides what the key can be used for.

Hybrid KEMs (ML-KEM + ECDH)

A hybrid KEM combines a post-quantum KEM (ML-KEM) with a traditional one (ECDH), to agree on a shared secret. This module implements the hybrid KEM MLKEM768-X25519 of draft-irtf-cfrg-concrete-hybrid-kems, also used by HPKE (draft-ietf-hpke-pq):

Hybrid KEM

Constant

Components

Public key

Ciphertext

MLKEM768-X25519

Hybrid.MLKEM768_X25519

ML-KEM-768 and X25519

1216 bytes

1120 bytes

MLKEM768-X25519 is the same as X-Wing. The other hybrid KEMs of the draft (MLKEM768-P256 and MLKEM1024-P384) are not supported yet, as their definition may still change.

A private key is a seed of 32 random bytes: the ML-KEM key and the ECDH key are both derived from it. The two private keys are never used on their own, or with another algorithm. The public key is the ML-KEM public key, concatenated to the X25519 public key (32 bytes).

The shared secret, result of the key agreeemnt, is always 32 bytes long.

With this module you can generate a new hybrid KEM key, and get its public key:

>>> from Crypto.PublicKey import Hybrid
>>>
>>> key = Hybrid.generate(param_set=Hybrid.MLKEM768_X25519)
>>> pub_key = key.public_key()

Currently, the keys of the hybrid KEMs can only be used with HPKE (Crypto.Protocol.HPKE), and they cannot be exported or imported.

API

Hybrid keys: a post-quantum key combined with a traditional one.

Currently, only the keys of the hybrid KEM X-Wing (ML-KEM-768 combined with X25519).

class Crypto.PublicKey.Hybrid.HybridKey(*, param_set, seed=None, pk=None)

Class defining a hybrid key (private or public): a post-quantum key and a traditional key, combined as defined by its parameter set. For the hybrid KEMs, an ML-KEM key and an ECDH key, as in draft-irtf-cfrg-concrete-hybrid-kems. Do not instantiate directly. Use generate() instead.

Variables:

param_set (ParamSet) – The combination of algorithms.

has_private()

True if this is a private key (for the hybrid KEMs, one that can decapsulate).

Return type:

bool

public_key()

A matching hybrid public key.

Return type:

HybridKey

Returns:

a new HybridKey object

Crypto.PublicKey.Hybrid.MLKEM768_X25519 = ParamSet.MLKEM768_X25519

Same as ParamSet.MLKEM768_X25519

class Crypto.PublicKey.Hybrid.ParamSet(value)

The combinations of a post-quantum and a traditional algorithm. The value of each member is the name of the combination.

Currently, the only member is a hybrid KEM (draft-irtf-cfrg-concrete-hybrid-kems, Section 4).

MLKEM768_X25519 = 'MLKEM768-X25519'

ML-KEM-768 and X25519 (same as X-Wing)

Crypto.PublicKey.Hybrid.generate(*, param_set, randfunc=None)

Generate a new hybrid private key.

Parameters:
  • param_set (ParamSet) – Mandatory. The combination of algorithms, for instance Hybrid.MLKEM768_X25519.

  • randfunc (callable) – Optional. The RNG to read the seed from (32 bytes for the hybrid KEMs). If None, Crypto.Random.get_random_bytes() is used.

Returns:

a new private key

Return type:

HybridKey