-
Notifications
You must be signed in to change notification settings - Fork 479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding a DeriveKeyPair functionality #1206
Comments
For reproducibility of any tests, IMO this is a functionality worth having. But then again, this is what Finally, if such new RFC-compliant and multicore-capable rand provider is needed (?) and available, why not discuss adding it to the pre-existing rand-sources with a new name and thus make it available to all language-wrappers (assuming |
I guess the question is to what extent new / custom randombytes algorithms can fix concurrency issues. The current algorithm (and its state) is globally defined. Not having a lot of concurrency experience, would we need something complex, like a randomness algorithm that keeps track of the current 'state' of the randomness for each thread? |
Well, the question is what degree of reproducibility is desired. But even if something simple (e.g., using thread-ID as seed) were not sufficient, ensuring proper synchronization of different threads on a global mutex shouldn't be overly complex. See e.g. different platform synchronization primitives implemented in openssl. |
To sidestep synchronisation issues, the implementations could be patched so that |
(This issue is blocking me from using liboqs to implement X25519Kyber768Draft00 in rust-hpke.) |
This came up again as (I believe) @bwesterb is trying to do HPKE with Kyber (using void crypto_sign_keypair_seeded(uint8_t *pk, uint8_t *sk, uint8_t[SEED_LEN] seed);
void crypto_sign_keypair(uint8_t *pk, uint8_t *sk) {
uint8_t seed[SEED_LEN];
randombytes(&seed, SEED_LEN);
crypto_sign_keypair_seeded(pk, sk, &seed);
} To me, it seems that a function pointer hack is just a more complicated way of achieving the same end result — in both cases, the implementation of every single scheme needs to be patched. The only case in which the function pointer mechanism might be better is if a scheme calls |
This is the case for Kyber, unfortunately. |
(I dug into this a little bit, we can't just make the |
The NIST KAT don't really seem to make implementations better :( |
I suppose the issue of multiple calls and KAT compatibility can be hacked around in the following way: void crypto_kem_keypair_seeded(uint8_t *pk, uint8_t *sk, uint8_t[SEED_LEN] seed);
void crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
uint8_t seed[SEED_LEN];
randombytes(&seed, CALL_1_LEN);
randombytes(&seed+CALL_1_LEN, CALL_2_LEN);
crypto_kem_keypair_seeded(pk, sk, &seed);
} Then this would only remain problematic for those schemes where |
@bwesterb do you only need derandomized key generation or also derandomized encapsulation? I'm amenable to adding an API for derandomized key generation, and having it exposed for Kyber. We'll have to work through doing it in all the Kyber implementations (we pull from both PQClean and PQCrystals), but it shouldn't be too hard to patch in. There's the question of whether we also do it for the other KEMs in liboqs, but I think it's less pressing for them, so I'm okay with doing it first in Kyber and leaving the rest to another time. |
My perspective would be that the |
I need thread-safe derandomized key generation to implement HPKE API. To validate test vectors, I also need derandomized encapsulation, but it's ok if that's hacky or not thread safe: I can make that work if liboqs-rust exposes
Great! |
Agreed. Derandomized key gen is also a little dangerous; I've seen some libraries include words like "hazardous" in the function API to flag that, do you think we should do so? Do you have any cycles for any of this? I am traveling next week and certainly won't have a chance to work on it then. |
Yeah.
Not for the coming two weeks at least. |
FYI @tedeaton I was talking to Peter Schwabe @cryptojedi who says there are some efforts underway to add a deterministic API to some of the Kyber implementations he works on. |
You can take a look at https://github.com/pq-crystals/kyber/blob/standard/ref/kem.c and https://github.com/pq-crystals/kyber/blob/standard/ref/kem.h to see what I did. |
It seems like this feature will be mostly "free" in the soon-to-be-integrated ML-KEM (formerly known as Kyber)—we would just have to add the necessary OQS API functions to expose the functionality. While we're at it, we might want to add this functionality to the older variant(s) of Kyber that we plan on supporting for the time being. |
OK for ML-KEM. What for other KEMs? Shall they simply throw a "Not Supported" exception/return NOK when used in conjunction with this API? |
That's what I had in mind. Alternatively, I suppose they could return an error code and call the randomized |
I'm not sure about this: Wouldn't this rather delay the inevitable (error occurring) for algorithms not geared to support this -- possibly to a (code) place where it's no longer obvious (creating support issues, well, probably an FAQ) for us? From the support perspective I'd much prefer a "hard exit" (or at the very least some error output) in such cases. |
Two questions:
|
Why would this need to be included in |
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: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.
The text was updated successfully, but these errors were encountered: