In the 3rd round of the NIST PQC competition, Kyber was selected for standardization. In the 4th round, NIST are now assessing BIKE, Classic McEliece, HQC and SIKE. Classic Mceliece has five main modes: McEliece348864. McEliece460896 524. McEliece6688128, McEliece6960119 and McEliece8192128. With this, we have large public keys, and relatively large private keys, but a small ciphertext size. Unfortunately, it is slow for key generation, but gives acceptable levels of encapsulation and decapsulation performance.
Classical Mceliece using Bouncy Castle and C# |
Key sizes
The Key sizes for Kyber and other PQC methdods are:
Type Public key size (B) Secret key size (B) Ciphertext size (B) ------------------------------------------------------------------------ Kyber512 800 1,632 768 Learning with errors (Lattice) Kyber738 1,184 2,400 1,088 Learning with errors (Lattice) Kyber1024 1,568 3,168 1,568 Learning with errors (Lattice) Bike128 1,541 3,114 1,573 Code-based Bike192 3,083 6,198 3,115 Code-based Bike256 5,122 10,276 5,154 Code-based HQC128 2,249 2,289 4,497 Code-based HQC192 4,522 4,562 9,042 Code-based HQC256 7,245 7,285 14,485 Code-based McEliece348864 261,120 6,492 196 Code based McEliece460896 524,160 13,608 156 Code based McEliece6688128 1,044,992 13,932 208 Code based McEliece6960119 1,047,319 13,948 194 Code based McEliece8192128 1,357,824 14,120 208 Code based NTRUhps2048509 699 935 699 Lattice NTRUhps2048677 930 1,234 930 Lattice NTRUhps4096821 1,230 1,590 1,230 Lattice SIKEp434 330 44 346 Isogeny SIKEp503 378 56 402 Isogeny SIKEp751 564 80 596 Isogeny SIDH 564 48 596 Isogeny LightSABER 672 1,568 736 Learning with rounding (Lattice) SABER 992 2,304 1,088 Learning with rounding (Lattice) FireSABER 1,312 3,040 1,472 Learning with rounding (Lattice)
Code
We can create a Dotnet console project for .NET 8.0 with:
dotnet new console
First we install the Bouncy Castle library:
dotnet add package BouncyCastle.Cryptography
Next some code:
namespace Cmce { using Org.BouncyCastle.Pqc.Crypto.Cmce; using Org.BouncyCastle.Security; class Program { static void Main(string[] args) { try { var size="mceliece348864"; if (args.Length >0) size=args[0]; var random = new SecureRandom(); var keyGenParameters = new CmceKeyGenerationParameters(random, CmceParameters.mceliece348864r3); if (size=="mceliece460896") keyGenParameters = new CmceKeyGenerationParameters(random, CmceParameters.mceliece460896r3); else if (size=="mceliece6688128") keyGenParameters = new CmceKeyGenerationParameters(random, CmceParameters.mceliece6688128r3); else if (size=="mceliece6960119") keyGenParameters = new CmceKeyGenerationParameters(random, CmceParameters.mceliece6960119r3); else if (size=="mceliece6960119") keyGenParameters = new CmceKeyGenerationParameters(random, CmceParameters.mceliece6960119r3); else if (size=="mceliece8192128") keyGenParameters = new CmceKeyGenerationParameters(random, CmceParameters.mceliece8192128r3); var CmceKeyPairGenerator = new CmceKeyPairGenerator(); CmceKeyPairGenerator.Init(keyGenParameters); var aKeyPair = CmceKeyPairGenerator.GenerateKeyPair(); var aPublic = (CmcePublicKeyParameters)aKeyPair.Public; var aPrivate = (CmcePrivateKeyParameters)aKeyPair.Private; var pubEncoded =aPublic.GetEncoded(); var privateEncoded = aPrivate.GetEncoded(); var bobCmceKemGenerator = new CmceKemGenerator(random); var encapsulatedSecret = bobCmceKemGenerator.GenerateEncapsulated(aPublic); var bobSecret = encapsulatedSecret.GetSecret(); var cipherText = encapsulatedSecret.GetEncapsulation(); var aliceKemExtractor = new CmceKemExtractor(aPrivate); var aliceSecret = aliceKemExtractor.ExtractSecret(cipherText); Console.WriteLine("Cmce-{0}",size); Console.WriteLine("Private key length:\t\t{0} bytes",aPrivate.GetEncoded().Length); Console.WriteLine("Public key length:\t\t{0} bytes",aPublic.GetEncoded().Length); Console.WriteLine("Ciphertext length:\t\t{0} bytes",cipherText.Length); Console.WriteLine("\nAlice private (first 50 bytes):\t{0}",Convert.ToHexString(aPrivate.GetEncoded())[..100]); Console.WriteLine("Alice public (first 50 bytes):\t{0}",Convert.ToHexString(aPublic.GetEncoded())[..100]); Console.WriteLine("\nCipher (first 50 bytes):\t{0}",Convert.ToHexString(cipherText)[..100]); Console.WriteLine("\nBob secret:\t\t{0}",Convert.ToHexString(bobSecret)); Console.WriteLine("Alice secret:\t\t{0}",Convert.ToHexString(aliceSecret)); } catch (Exception e) { Console.WriteLine("Error: {0}",e.Message); } } } }
A sample run for Mceliece 348864:
Cmce-mceliece348864 Private key length: 6492 bytes Public key length: 261120 bytes Ciphertext length: 96 bytes Alice private (first 50 bytes): D1400431A9A9A613AD8BE4DBD5EB83F06DB270BF41F4F5BF3EAD0A9A604D3D8CFFFFFFFF00000000FB0BA600F100A0020409 Alice public (first 50 bytes): 7B832C2A27C75DCAF27A189DE33550777356AE5FD9E26B3541F8E1A4475369EEDD9AAA5DAB04C48D339546986997AAA4F776 Cipher (first 50 bytes): 55DC03B3965AAB2CD0EB3399894ED0E46ABB853B3ED61316AB99974AE5331A61B58028BC0206692028956DD89E3B6ECB6A3B Bob secret: 78AF1943C129D7296744E4C2D298DAE5 Alice secret: 78AF1943C129D7296744E4C2D298DAE5
and for Mceliece 460896:
Cmce-mceliece460896 Private key length: 13608 bytes Public key length: 524160 bytes Ciphertext length: 156 bytes Alice private (first 50 bytes): E9A425034F39382A139313C0F8B1033D6964776723CE20A17B74ED4F9B825082FFFFFFFF00000000D419E11623092810A10D Alice public (first 50 bytes): 74D04D58286B87EC03081B5B7362DF5CDC265CAB21A92F0D39F3EAC7DDD48AA4192181BFD5926B50DA5B7FA85B535A5483F4 Cipher (first 50 bytes): 37FE5AC631FA220E195DAF9081B30B47B792D1DC0FD708DE1B7E7E602A961D9056E3BBAC76845D29BFF841952D78EDBDF29C Bob secret: FA2FD597E10738E78E6C8C9BB07A9C0BAB5D043A1F16A61A Alice secret: FA2FD597E10738E78E6C8C9BB07A9C0BAB5D043A1F16A61A