-
Notifications
You must be signed in to change notification settings - Fork 144
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
Implement Classic McEliece #378
base: main
Are you sure you want to change the base?
Conversation
@octeep thanks for pushing this. Also, could you please squash your commits. We will review this code closely. Definitely key generation takes lots of time (ARM64 tests timed out, while x64's not). What about adding a build constraint to compile this code only on x64? What do you think @bwesterb ? |
I'll have a look tomorrow. |
I've squashed my commit. This probably shouldn't be merged yet since the Classic McEliece team might soon release their round 4 specs and software soon (See this). It might be better to wait for them to publish the round 4 so this PR can be updated accordingly. |
44f1fbf
to
820e065
Compare
Thanks for this @octeep
Ok. Can I ask you how did this implementation came to be: is it a fresh implementation from the spec or did you translate an existing implementation ( I had an initial look today. To set expectations: it will of course take quite some time to carefully review this. Some initial comments:
|
Most of the code is translated from the 'Optimized Implementation' in the round 3 NIST submission package by the Classic McEliece team. However, when some methods cannot directly be ported from C (for example due to pointer arithmetic), the code is lifted from the Rust implementation instead. The Rust implementation is also based on the Optimized Implementation as far as I can tell.
I unfortunately do not have much experience with Go optimization. I also want to note that when I compile the C optimized implementation with vectorization explicitly disabled, the performance is only slightly faster than Go. When I compile the C optimized implementation and tell gcc to show the optimization tree, I see that gcc has performed vectorization automatically, which is why it is much faster than Go. The
If we are talking about optimizing If we are talking about optimizing all the components with SIMD then no, I haven't given much thoughts into it.
I will look into that. I don't think reducing it to a few hashes can work since the test cases contain sample inputs. Maybe we can compress it or represent these inputs in raw bytes rather than as hexadecimal ASCII.
I will try to document the code to the best of my understanding. |
I have managed to trim down |
Thanks again for your efforts!
Ok! Please add appropriate attributions.
Yes, that's a great plan! (For those reading along:
I'll get back to this when I found time to properly study the code.
Great! If you're unsure about certain parts, please leave a comment as such for us to fill in. |
@armfazh ? |
After bzip2-ing that file, size gets down to 50 KB, which I think is acceptable. |
As a general comment, please introduce |
I'm not sure how I should add attributions here. I have added a notice on each
I am trying to do that in the
|
That should be enough for now.
Cool. |
Ok good news: I managed to port the |
Good job! |
This reverts commit c563649.
I've updated the implementation to the round 4 specification. It passes KAT tests and finishes in 10 minutes on CI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @octeep, so far I have checked the field arithmetic, it looks ok and there are some minor changes requested.
I will continue the review of other parts of the code.
Co-authored-by: Armando Faz <[email protected]>
Hello 👋 , just wanted to say this change is desired, and that I hope code review proceeds in the near future! 🚀 |
Hello, just wanted to inquire if there's been any movement on this! Would love to see this get reviewed soon. |
Hi, I will continue with the review of this PR in the next couple days. Thanks for your patience. |
Any updates on this one? |
I am also really interested in this PR as I am planning to use this for the Go implementation of the WireGuard Rosenpass Key Exchange. |
I noticed that the current implementation differs from liboqs with respect to the ciphertext length. |
The file headers are still mentioning round 3:
|
@armfazh Can we remove the on-hold label from the issue? Round 4 specs have been released. There is nothing blocking this from getting finished :) |
Thanks for pointing that out, I've fixed that in a new commit.
It would appear that liboqs is still using the round 3 specification which explains the difference in ciphertext length. Mine follows the round 4 specification and the produced ciphertexts are checked against the KAT tests provided by the official Classic McEliece website. |
Hi @bwesterb, @pufferffish, @armfazh, is there something I can do to support you in getting this implementation merged? Thanks :) |
@stv0g we appreciate a code review, our team will be providing feedback as we get more bandwidth. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a preliminary review. I will need to go through the GF arithmetics and templates more thouroughly.
@@ -155,6 +155,16 @@ func Example_schemes() { | |||
// Kyber512 | |||
// Kyber768 | |||
// Kyber1024 | |||
// mceliece348864 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason you have named the schemes with all-lowercase letters while the other PQ KEM schemes use CamelCase?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add Classic McEliece to the file-level comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we generate this file using some meta-programming?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we generate this file using some meta-programming?
} | ||
|
||
var ( | ||
McElieceParam348864 = Param{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we maybe consider also adding pc
variants of Classic McEliece including a 32-byte plaintext confirmation.
This would be desirable as liboqs always adds/expects the plaintext confirmation which makes incompatible with this implementation.
SysT: 128, | ||
} | ||
Instances = []Instance{ | ||
{Name: "mceliece348864", Param: McElieceParam348864}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to use names in line with liboqs here:
https://github.com/open-quantum-safe/liboqs/blob/6e1f49aa48971b0fc8658e94ca41d1ad4fe480ee/src/kem/kem.h#L42
This also matches the capitalization of e.g. Kyber512
@stv0g thanks for the review. It's been a while since I've worked on this and recently I've been busy with work so I can't promise I can get back to your reviews soon. If you'd like to I can give you write access to my fork repo so you can directly work on this pull request. |
// expanding and updating the seed | ||
err := shake256(r[:], seed[0:33]) | ||
if err != nil { | ||
panic(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we return the error in DeriveKeypair()
.
I would say panic()
these code paths should be discouraged.
|
||
func (*scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { | ||
if len(seed) != seedSize { | ||
panic("seed must be of length EncapsulationSeedSize") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as below. Can we return an error here?
Hi there, Interested in seeing this move forward, any updates? |
Hi. I get that everyone is busy doing other things and I also understand that I'm essentially the most impatient person in the world which is why I've decided to simply lift all this code into a fork for use with katzenpost... with proper attribution of course. However I would much rather this pull request get merged and the code maintained by you guys. I hate maintaining forks. But I hate waiting for things even more. |
It looks like code contributions from your code contributor has stalled. i suggested you fork his dev branch and open a new pull request... and fix all the code corrections you were telling them to fix. If you don't do this, then this PR will likely continue to fester here meanwhile Rome is burning... society cracking at the foundations, abortion clinics need PQ KEMs like this one. |
This is a draft of a Classic McEliece that implements all the parameters specified in the round 3 submission. It passes the KAT tests provided in the official website.
The current major problem right now is that public key generation takes so much time it causes tests on CI to timeout and fail. This is because the Gaussian Elimination loop inside
pkGen
inpk_gen.go
can take millions of iterations for larger parameters. Vectorization should be able to make it faster by like 30x but I haven't implemented it yet. Currently there are only generic Go implementations.Some test data outside of the KAT test are lifted from a Rust implementation. These test data are to ensure that some specific functions work correctly.
Closes #360