McEliece is a post-quantum key exchange mechanism, and a finalist for the NIST PQC competition [2]. This page uses various methods including mceliece348864, mceliece460896, mceliece6688128, mceliece6960119 and mceliece8192128. In McEliece methods, we have three main parameters: \(m\), \(n\) and \(t\). With mceliece348864, we have a Level 1 security level with a public key size of 261,120 bytes, a private key size of 6,492 bytes, and a cipher text size of 128 bytes. mceliece460896 has a Level 3 security level with a public key size of 524,160 bytes, a private key size of 13,608 bytes, and a cipher text size of 188 bytes. mceliece460896 has a Level 5 security level with a public key size of 1,0454,992 bytes, a private key size of 13,932 bytes, and a cipher text size of 240 bytes. In this case, we will implement mceliece348864.
McEliece Key Exchange and Public Key Encryption in Rust |
Outline
The following is the derived key size and cipher text (in bytes) of each of the core methods [1]:
m n t level | public key secret key ciphertext -------------------------------------------------------------------------- mceliece348864 12 3,488 64 1 | 261,120 6,492 128 mceliece460896 13 4,608 94 3 | 524,160 13,608 188 mceliece6688128 13 6,688 128 5 | 1,044,992 13,932 240 mceliece6960119 13 6,960 119 5 | 1,047,319 13,948 226 mceliece8192128 13 8,192 128 5 | 1,357,824 14,120 240
The following defines the key sizes for Kyber, SABER, NTRU and McEliece:
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) 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) McEliece348864 261,120 6,452 128 Code based McEliece460896 524,160 13,568 188 Code based McEliece6688128 1,044,992 13,892 240 Code based McEliece6960119 1,047,319 13,948 226 Code based McEliece8192128 1,357,824 14,120 240 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
Code
First we create the project with:
cargo new mce
We then go into the mce folder, and add the following to the cargo.toml file:
[package] name = "mce" version = "0.1.0" edition = "2021" [dependencies] classic-mceliece-rust = "3.0" rand = "^0.8.5" hex="^0.4"
The code is then::
use classic_mceliece_rust::{keypair, encapsulate, decapsulate}; use classic_mceliece_rust::{CRYPTO_BYTES, CRYPTO_PUBLICKEYBYTES, CRYPTO_SECRETKEYBYTES}; use hex; fn main() { let mut rng = rand::thread_rng(); let mut public_key_buf = [0u8; CRYPTO_PUBLICKEYBYTES]; let mut secret_key_buf = [0u8; CRYPTO_SECRETKEYBYTES]; let (public_key, secret_key) = keypair(&mut public_key_buf, &mut secret_key_buf, &mut rng); println!("\nBob public key (showing first 32 out of {} bytes): {:.32}", CRYPTO_PUBLICKEYBYTES,hex::encode(public_key.as_array())); println!("\nBob secret key (showing first 32 out of {} bytes): {:.32}",CRYPTO_SECRETKEYBYTES,hex::encode(secret_key.as_array())); let mut shared_secret_bob_buf = [0u8; CRYPTO_BYTES]; let (ciphertext, shared_secret_bob) = encapsulate(&public_key, &mut shared_secret_bob_buf, &mut rng); let mut shared_secret_alice_buf = [0u8; CRYPTO_BYTES]; let shared_secret_alice = decapsulate(&ciphertext, &secret_key, &mut shared_secret_alice_buf); println!("\nCiphertext (Bob to Alice) (showing {} bytes): {}",ciphertext.as_array().len(),hex::encode(ciphertext.as_array())); println!("\nBob key: (showing {} bytes) {}",shared_secret_bob.as_array().len(),hex::encode(shared_secret_bob.as_array())); println!("\nAlice key: (showing {} bytes) {}",shared_secret_alice.as_array().len(),hex::encode(shared_secret_alice.as_array())); }
Finally we simply build with:
cargo build
A sample run is:
Bob public key (showing first 32 out of 261120 bytes): 4b44ae97d30a04f2ade8334a4817b5cc Bob secret key (showing first 32 out of 6492 bytes): 76ac75d052f030692d334d843bc29ee7 Ciphertext (Bob to Alice) (showing 96 bytes): f40bff3d7928cd70cd1cf8a04daaacbf67168585a79fc57a28fef71203771a2d572229f29079bf6fe1713e7b3444c9badaebd7a7277ef6c88db9f02a27b3ba98b6f82743b2ba4b47d781b5fc5b7657ee10ef5d30971c2f2d2a8395898e8c2fe0 Bob key: (showing 32 bytes) bb2853e129206f1d9e2802a5e6bd93265545b0369eb91750d799b876d870ff30 Alice key: (showing 32 bytes) bb2853e129206f1d9e2802a5e6bd93265545b0369eb91750d799b876d870ff30
We can see that the shared key for Bob and Alice is 32 bytes long (256 bits). The public key is 261,120 bytes long, and the secret key is 6492 bytes. The cipher text is 96 bytes long.
Reference
[1] Chen, M. S., & Chou, T. Classic McEliece on the ARM Cortex-M4 [here].
[2] McEliece, R. J. (1978). A public-key cryptosystem based on algebraic. Coding Thv, 4244, 114-116.