Kyber

Build Status Crates NPM License dependency status

A rust implementation of the Kyber algorithm, a KEM standardised by the NIST Post-Quantum Standardization Project.

This library: * Is nostd compatible and needs no allocator, suitable for embedded devices. * Reference files contain no unsafe code and are written in pure rust. * On x8664 platforms offers an avx2 optimized version, which includes assembly from the C reference repo. * Compiles to WASM using wasm-bindgen and has a ready-to-use binary published on NPM.

See the features section for different options regarding security levels and modes of operation. The default security setting is kyber768.

It is recommended to use Kyber in a hybrid system alongside a traditional key exchange algorithm such as X25519.

Please also read the security considerations before use.

Minimum Supported Rust Version: 1.56.0


Installation

shell cargo add pqc_kyber

Usage

rust use pqc_kyber::*;

For optimisations on x86 platforms enable the avx2 feature and the following RUSTFLAGS:

shell export RUSTFLAGS="-C target-feature=+aes,+avx2,+sse2,+sse4.1,+bmi2,+popcnt"


Key Encapsulation

```rust // Generate Keypair let keys_bob = keypair(&mut rng);

// Alice encapsulates a shared secret using Bob's public key let (ciphertext, sharedsecretalice) = encapsulate(&keys_bob.public, &mut rng)?;

// Bob decapsulates a shared secret using the ciphertext sent by Alice let sharedsecretbob = decapsulate(&ciphertext, &keys_bob.secret)?;

asserteq!(sharedsecretalice, sharedsecret_bob); ```


Unilaterally Authenticated Key Exchange

```rust let mut rng = rand::thread_rng();

// Initialize the key exchange structs let mut alice = Uake::new(); let mut bob = Uake::new();

// Generate Bob's Keypair let bob_keys = keypair(&mut rng);

// Alice initiates key exchange let clientinit = alice.clientinit(&bob_keys.public, &mut rng);

// Bob authenticates and responds let serverresponse = bob.serverreceive( clientinit, &bobkeys.secret, &mut rng )?;

// Alice decapsulates the shared secret alice.clientconfirm(serverresponse)?;

// Both key exchange structs now have the same shared secret asserteq!(alice.sharedsecret, bob.shared_secret); ```


Mutually Authenticated Key Exchange

Follows the same workflow except Bob requires Alice's public keys:

```rust let mut alice = Ake::new(); let mut bob = Ake::new();

let alicekeys = keypair(&mut rng); let bobkeys = keypair(&mut rng);

let clientinit = alice.clientinit(&bob_keys.public, &mut rng);

let serverresponse = bob.serverreceive( clientinit, &alicekeys.public, &bob_keys.secret, &mut rng )?;

alice.clientconfirm(serverresponse, &alice_keys.secret)?;

asserteq!(alice.sharedsecret, bob.shared_secret); ```


Errors

The KyberError enum has two variants:


Features

If no security level is specified then kyber768 is used by default as recommended by the authors. It is roughly equivalent to AES-192. Apart from the two security levels, all other features can be combined as needed. For example:

toml [dependencies] pqc_kyber = {version = "0.6.0", features = ["kyber512", "90s", "avx2"]}

| Feature | Description | |-----------|------------| | std | Enable the standard library | | kyber512 | Enables kyber512 mode, with a security level roughly equivalent to AES-128.| | kyber1024 | Enables kyber1024 mode, with a security level roughly equivalent to AES-256. A compile-time error is raised if more than one security level is specified.| | 90s | Uses AES256 in counter mode and SHA2 as a replacement for SHAKE. This can provide hardware speedups in some cases.| | 90s-fixslice | Uses a fixslice implementation of AES256 by RustCrypto, this provides greater side-channel attack resistance, especially on embedded platforms | | avx2 | On x86_64 platforms enable the optimized version. This flag is will cause a compile error on other architectures. | | wasm | For compiling to WASM targets| | nasm | Uses Netwide Assembler avx2 code instead of GAS for portability. Requires a nasm compiler: https://www.nasm.us/ | | zeroize | This will zero out the key exchange structs on drop using the zeroize crate |

| benchmarking | Enables the criterion benchmarking suite |

Testing

The runalltests script will traverse all possible codepaths by running a matrix of the security levels, variants and crate features.

Known Answer Tests require deterministic rng seeds, enable kyber_kat in RUSTFLAGSto use them. Using this outside of cargo test will result in a compile-time error. The test vector files are quite large, you will need to build them yourself from the C reference code. There's a helper script to do this here.

```bash

This example runs the basic tests for kyber768

cargo test

This runs the KATs for kyber512 in 90's mode

RUSTFLAGS='--cfg kyber_kat' cargo test --features "kyber512 90s" ```

See the testing readme for more comprehensive info.


Benchmarking

Uses criterion for benchmarking. If you have GNUPlot installed it will generate statistical graphs in ./target/criterion/.

You will need to enable the benchmarking feature.

See the benchmarking readme for information on correct usage.


Fuzzing

The fuzzing suite uses honggfuzz, installation and instructions are on the fuzzing page.


WebAssembly

This library has been compiled into web assembly and published as a npm package. Usage instructions are here:

https://www.npmjs.com/package/pqc-kyber

Which is also located here in the wasm readme

To install:

shell npm i pqc-kyber

To compile the wasm files yourself you need to enable the wasm feature.

For example, using wasm-pack:

shell wasm-pack build -- --features wasm

Which will export the wasm, javascript and typescript files into ./pkg/.

To compile a different variant into a separate folder: shell wasm-pack build --out-dir pkg_kyber512/ -- --features "wasm kyber512"

There is also a basic html demo in the www folder.

From the www folder run:

shell npm run start


Security Considerations

While much care has been taken porting from the C reference codebase, this library has not undergone any third-party security auditing nor can any guarantees be made about the potential for underlying vulnerabilities in LWE cryptography or potential side-channel attacks arising from this implementation.

Kyber is relatively new, it is advised to use it in a hybrid key exchange system alongside a traditional algorithm like X25519 rather than by itself.

For further reading the IETF have a draft construction for hybrid key exchange in TLS 1.3:

https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-04.html

You can also see how such a system is implemented here in C by OpenSSH

Please use at your own risk.


About

Kyber is an IND-CCA2-secure key encapsulation mechanism (KEM), whose security is based on the hardness of solving the learning-with-errors (LWE) problem over module lattices. It is the final standardised algorithm resulting from the NIST post-quantum cryptography project.

The official website: https://pq-crystals.org/kyber/

Authors of the Kyber Algorithm:


Contributing

Contributions welcome. For pull requests create a feature fork and submit it to the development branch. More information is available on the contributing page


Alternatives

The PQClean project has rust bindings for their Kyber C codebase:

https://github.com/rustpq/pqcrypto