At present, CRYSTALS (Cryptographic Suite for Algebraic Lattices) supports two quantum robust mechanisms: Kyber for key-encapsulation mechanism (KEM) and key exchange; and Dilithium for a digital signature algorithm. CRYSTALS Dilithium uses lattice-based Fiat-Shamir schemes, and produces one of the smallest signatures of all the post-quantum methods, and with relatively small public and private key sizes. The three main implements for the parameters used are: Dilithium 2, Dilithium 3 and Dilithium 5. Overall, Dilithium 3 is equivalent to a 128-bit signature, and is perhaps the starting point for an implementation.
CRYSTALS Dilithium using Bouncy Castle and C# |
Outline
Performance evaluation
The following provides an analysis of the PCQ methods for digital signing:
Method Public key size Private key size Signature size Security level ------------------------------------------------------------------------------------------------------ Crystals Dilithium 2 (Lattice) 1,312 2,528 2,420 1 (128-bit) Lattice Crystals Dilithium 3 1,952 4,000 3,293 3 (192-bit) Lattice Crystals Dilithium 5 2,592 4,864 4,595 5 (256-bit) Lattice Falcon 512 (Lattice) 897 1,281 690 1 (128-bit) Lattice Falcon 1024 1,793 2,305 1,330 5 (256-bit) Lattice Rainbow Level Ia (Oil-and-Vineger) 161,600 103,648 66 1 (128-bit) Multivariate (UOV) Rainbow Level IIIa 861,400 611,300 164 3 (192-bit) Multivariate (UOV) Rainbow Level Vc 1,885,400 1,375,700 204 5 (256-bit) Multivariate (UOV) Sphincs SHA256-128f Simple 32 64 17,088 1 (128-bit) Hash-based Sphincs SHA256-192f Simple 48 96 35,664 3 (192-bit) Hash-based Sphincs SHA256-256f Simple 64 128 49,856 5 (256-bit) Hash-based Picnic 3 Full 49 73 71,179 3 (192-bit) Symmetric GeMSS 128 352,188 16 33 1 (128-bit) Multivariate (HFEv-) GeMSS 192 1,237,964 24 53 1 (128-bit) Multivariate (HFEv-) RSA-2048 256 256 256 ECC 256-bit 64 32 256
For performance on M4 (ARM Cortex-M4 dev) [1] and measured in CPU operations per second. Note, no Rainbow assessment has been performed in [1], so LUOV (an Oil-and-Vinegar method) has been used to give an indication of performance levels:
Method Key Generation Sign Verify ------------------------------------------------------------------------------------------------------ Crystals Dilithium 2 1,400,412 6,157,001 1,461,284 1 (128-bit) Lattice Crystals Dilithium 3 2,282,485 9,289,499 2,228,898 3 (192-bit) Lattice Crystals Dilithium 5 3,097,421 8,469,805 3,173,500 5 (256-bit) Lattice Falcon 512 (Lattice) 197,793,925 38,090,446 474,052 1 (128-bit) Lattice Falcon 1024 480,910,965 83,482,883 977,140 3 (256-bit) Lattice Rainbow Level Ia 41,347,565 101,874,410 77,433,705 1 (128-bit) UOV Rainbow Level IIIa 66,072,054 123,878,322 95,330,045 3 (192-bit) UOV Rainbow Level Vc 109,063,616 405,205,796 269,012,028 5 (256-bit) UOV Sphincs SHA256-128f Simple 16,552,135 521,963,206 20,850,719 1 (128-bit) Hash-based Sphincs SHA256-192f Simple 24,355,501 687,693,467 35,097,457 3 (128-bit) Hash-based Sphincs SHA256-256f Simple 64,184,968 1,554,168,401 36,182,488 5 (128-bit) Hash-based
For stack memory size on an ARM Cortex-M4 device [1] and measured in bytes. Note, no Rainbow assessment has been performed in [1], so LUOV (an Oil-and-Vinegar method) has been used to give an indication of performance levels:
Method Key generation Sign Verify ---------------------------------------------------------------- Crystals Dilithium 2 (Lattice) 36,424 61,312 40,664 Crystals Dilithium 3 50,752 81,792 55,000 Crystals Dilithium 5 67,136 104,408 71,472 Falcon 512 (Lattice) 1,680 2,484 512 Falcon 1024 1,680 2,452 512 Rainbow Level Ia (Oil-and-Vineger) 2,969 4,720 2,732 Rainbow Level IIIa 3,216 3,224 1,440 Rainbow Level Vc 3,736 6,896 4,928 Sphincs SHA256-128f Simple 2,192 2,248 2,544 Sphincs SHA256-192f Simple 3,512 3,640 3,872 Sphincs SHA256-256f Simple 5,600 5,560 5,184
For code size on an ARM Cortex-M4 device [1] and measured in bytes. Note, no Rainbow assessment has been performed in [1], so LUOV (an Oil-and-Vinegar method) has been used to give an indication of performance levels:
Method Memory (Bytes) ------------------------------------------------- Crystals Dilithium 2 (Lattice) 13,948 Crystals Dilithium 3 13,756 Crystals Dilithium 5 13,852 Falcon 512 (Lattice) 117,271 Falcon 1024 157,207 Rainbow Level Ia (Oil-and-Vineger) 404,920 Rainbow Level IIIa 405,412 Rainbow Level Vc 405,730 Sphincs SHA256-128f Simple 4,668 Sphincs SHA256-192f Simple 4,676 Sphincs SHA256-256f Simple 5,084
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 Dilithium { using Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium; using Org.BouncyCastle.Security; class Program { static void Main(string[] args) { try { var msg="Hello"; var method="Dilithium2"; if (args.Length >0) msg=args[0]; if (args.Length >1) method=args[1]; var random = new SecureRandom(); var keyGenParameters = new DilithiumKeyGenerationParameters(random, DilithiumParameters.Dilithium2); if (method=="Dilithium3") keyGenParameters = new DilithiumKeyGenerationParameters(random, DilithiumParameters.Dilithium3); if (method=="Dilithium5") keyGenParameters = new DilithiumKeyGenerationParameters(random, DilithiumParameters.Dilithium5); if (method=="Dilithium2Aes") keyGenParameters = new DilithiumKeyGenerationParameters(random, DilithiumParameters.Dilithium2Aes); if (method=="Dilithium3Aes") keyGenParameters = new DilithiumKeyGenerationParameters(random, DilithiumParameters.Dilithium3Aes); if (method=="Dilithium5Aes") keyGenParameters = new DilithiumKeyGenerationParameters(random, DilithiumParameters.Dilithium5Aes); var keyPairGen = new DilithiumKeyPairGenerator(); keyPairGen.Init(keyGenParameters); var keyPair = keyPairGen.GenerateKeyPair(); var pubKey = (DilithiumPublicKeyParameters)keyPair.Public; var privKey = (DilithiumPrivateKeyParameters)keyPair.Private; // Signing var aliceSign = new DilithiumSigner(); aliceSign.Init(true, privKey); var signature = aliceSign.GenerateSignature(System.Text.Encoding.UTF8.GetBytes(msg)); // verify signature var bobVerify = new DilithiumSigner(); bobVerify.Init(false, pubKey); var rtn = bobVerify.VerifySignature(System.Text.Encoding.UTF8.GetBytes(msg), signature); Console.WriteLine("Message:\t{0}",msg); Console.WriteLine("Method:\t\t{0}",method); Console.WriteLine("\nPublic key (length):\t{0} bytes",pubKey.GetEncoded().Length); Console.WriteLine("Alice Public key (first 50 bytes)):\t{0}",Convert.ToHexString(pubKey.GetEncoded())[..100]); Console.WriteLine("\nPrivate key (length):\t{0} bytes",privKey.GetEncoded().Length); Console.WriteLine("Alice Private key (first 50 bytes)):\t{0}",Convert.ToHexString(privKey.GetEncoded())[..100]); Console.WriteLine("\nSignature (length):\t{0} bytes",signature.Length); Console.WriteLine("Signature (first 50 bytes):\t\t{0}",Convert.ToHexString(signature)[..100]); Console.WriteLine("\nVerified:\t{0}",rtn); } catch (Exception e) { Console.WriteLine("Error: {0}",e.Message); } } } }
A sample run with Dilithium5 gives:
Message: Post Quantum Crypto Method: Dilithium5 Public key (length): 2592 bytes Alice Public key (first 50 bytes)): D7B5D80F7973C3B99440F9656A4172763DAF79B08E545B04AE34C10435590DD3FF1C6AB2F7D208BFA8E39CA4EF78997F122F Private key (length): 4864 bytes Alice Private key (first 50 bytes)): D7B5D80F7973C3B99440F9656A4172763DAF79B08E545B04AE34C10435590DD3D56852FA31D7176C431ED2F9E7B0EED9E51A Signature (length): 4595 bytes Signature (first 50 bytes): 8BD6DB2FFFAAB5EB33EC2263EB258C0172AC5CCDEF2D15B38410EF63A7B02D6B57A372E4E3380B72BC4643E278348545D03B Verified: True