Repository: open-quantum-safe/liboqs

Issue #1206: Adding a DeriveKeyPair functionality
Created: 2022-04-27T21:30:19Z
When a KEM keypair is derived in liboqs, it relies on randomness using rand.h. In some situations, it's useful to generate keypairs deterministically from a seed. When RFC9180 defines a KEM, they include a DeriveKeyPair option to generate keypairs deterministically from a seed. As an example use case, Messaging Layer Security makes extensive use of functionality to share multiple keypairs by communicating seeds. I think it would be nice to match RFC9180 and add a functionality to deterministically derive a keypair from a seed.
This is kind of possible in liboqs currently. You can set the randomness to use OQS_RAND_alg_nist_kat, and derive all the randomness used from a seed, but this is a somewhat imperfect solution for a few reasons:

The seed must be exactly 48 bytes
It references a global variable, resulting in concurrency issues
Modifying the randomness used is (to my knowledge) not available with any of the liboqs language wrappers

I'm curious if others think this is a functionality worth adding and if so, what the proper way to tackle it might be. Some schemes, like Kyber, are already constructed in such a way that everything is derived from a seed, but liboqs provides limited ability to set that seed. I suspect the situation for other schemes is much more complex.

Duplicate issue #2003: Support derivation of KEM key pairs
Created: 2024-11-20T16:20:20Z
In #1994, we have been discussing adding support for the "seed" format of ML-KEM keys.  As I looked into implementation, it occurred to me that the approach outlined in that issue is not sufficient for implementing HPKE and protocols such as MLS and TLS ECH that rely on it.  The proposed solution here is to add a "derive key pair" method to the KEM interface, that would provide the correspondingly-named function in the HPKE specification.
The addition to the KEM struct would be something like:
	/** The length, in bytes, of a seed from which a keypair can be derived for this KEM. */
	size_t length_seed;

	/**
	 * Keypair generation from a seed.
	 *
	 * Caller is responsible for allocating sufficient memory for `public_key` and
	 * `secret_key`, based on the `length_*` members in this object or the per-scheme
	 * compile-time macros `OQS_KEM_*_length_*`.
	 *
	 * @param[out] public_key The public key represented as a byte string.
	 * @param[out] secret_key The secret key represented as a byte string.
	 * @param[in] seed The entropy from which the key pair is derived.
	 * @return OQS_SUCCESS or OQS_ERROR
	 */
	OQS_STATUS (*derive_keypair)(uint8_t *public_key, uint8_t *secret_key, const uint8_t *seed);
This approach would support HPKE and downstream protocols, and would remove the need for a separate ML-KEM instance based on the seed, since the application could expand the seed themselves.
It seems like the major challenge here would be addressing all the existing KEMs.  I'm not all that familiar with the copy_from_upstream tooling, but presumably we would add a parameter to the YAML file to point to an implementation of this method.  If we could generate a default "always return failure" function when that parameter isn't present, it seems like that would enable a smooth migration.

Closing comment (2024-11-20T17:01:53Z): Thanks, @SWilson4, closing this as a dup of #1206.