# Clatter 🔊

[![Crates.io Version](https://img.shields.io/crates/v/clatter?style=flat-square)](https://crates.io/crates/clatter)
[![docs.rs](https://img.shields.io/docsrs/clatter?style=flat-square)](https://docs.rs/clatter/latest/clatter/)
[![GitHub branch check runs](https://img.shields.io/github/check-runs/jmlepisto/clatter/main?style=flat-square)](https://github.com/jmlepisto/clatter/actions)

`no_std` compatible, pure Rust implementation of the [**Noise protocol framework**](https://noiseprotocol.org/noise.html)
with support for [**Post Quantum (PQ) extensions**](https://doi.org/10.1145/3548606.3560577) as presented by
Yawning Angel, Benjamin Dowling, Andreas Hülsing, Peter Schwabe, and Fiona Johanna Weber.

Main targets of this crate are **correctness**, extensibility, and strict `no_std` compatibility
and those come with the small drawback of more verbose user experience with some boilerplate.
If you don't need PQ functionality and are developing for a regular target, you probably are better
off using these instead:

* [`snow`](https://github.com/mcginty/snow)
* [`noise-rust`](https://github.com/blckngm/noise-rust)

Basis of this implementation relies heavily on the abovementioned crates and I'm extending
huge thanks to the developers for their effort!

⚠️ **Warning** ⚠️

* This library has not received any formal audit
* While we enable some cryptographic providers by default, it is up to **you** to get familiar with those and decide if they meet your security and integrity requirements
* Post-Quantum cryptography generally is not as established and mature as classical cryptography. Users are encouraged to implement hybrid encryption schemes with classical
crypto primitives incorporated to provide additional security in case of a catastrophic flaw in the post-quantum algorithms.
Clatter provides:

  * [`HybridHandshake`](https://docs.rs/clatter/latest/clatter/type.HybridHandshake.html) - *true hybrid* handshake which combines both DH and KEM operations in the same handshake messages.
  * [`HybridDualLayerHandshake`](https://docs.rs/clatter/latest/clatter/struct.HybridDualLayerHandshake.html) - *outer-encrypts-inner* style piped handshake with cryptographic binding between the layers.
  * [`DualLayerHandshake`](https://docs.rs/clatter/latest/clatter/struct.DualLayerHandshake.html) - *outer-encrypts-inner* style piped handshake with fully independent layers.

📖 **Documentation** 📖

* [`docs.rs`](https://docs.rs/clatter/latest/clatter/)
* [`examples/`](examples/)

## Noise Protocol

This crate tracks Noise protocol framework **revision 34**. As of now we omit support for the following features:

* Handshake pattern parsing support - Handshakes have to be instantiated with the correct primitives compile-time
* Curve 448 DH support - No suitable Rust implementation exists for our requirements
* Deferred pattern support - Can be implemented by the user
* Fallback pattern support - Can be implemented by the user

### PSK validity rule

Clatter adopts a modified interpretation of the PSK validity rule for post-quantum patterns, the original rule being:

> A party may not send any encrypted data after it processes a "psk" token unless it
> has previously sent an ephemeral public key (an "e" token), either before or after
> the "psk" token.

When post-quantum patterns are used, sending either an `e` or `ekem` token provides the required
self-chosen randomness equivalent to the `e` token in classic Noise patterns. Both tokens result
in the `MixKey` Noise function being called with derived key material from a self-chosen randomness
source **before** any encryption occurs, ensuring the same security guarantees as the original rule.

`skem` also satisfies this requirement if it comes before any `psk` tokens in the message pattern.

## PQ? NQ? Why should I care?

This crate refers to classical Noise handshakes as NQ handshakes (non-post-quantum). But what does a
PQ (post-quantum) handshake actually mean?

**Key encapsulation mechanism** or **KEM** is a public-key encryption system that allows a sender
to securely transmit a short shared secret to a receiver using the receivers public key. This shared
secret can then be used as a basis for further *symmetric* encrypted communication.

Classical Noise uses **Diffie-Hellman** or **DH** key exchanges to establish a shared secret between
the parties. During a DH key exchange the shared secret is generated by both parties through mutual
computations on the publicly transmitted data - whereas **KEMs** are used to transmit the shared
secret directly.

The motivation to use KEMs lies in the fact that there are KEM algorithms that are currently thought to
be secure against cryptoanalytic attacks by quantum computers. The DH algorithms used by Noise rely on
the difficulty of mathematical problems that can be easily solved on a powerful quantum computer.
Such quantum computers do not exist yet, but the world is already shifting towards quantum-safe
cryptography.

[**Post Quantum Noise**](https://doi.org/10.1145/3548606.3560577) by Yawning Angel et al. introduced
methods and rules for substituting DH key exchanges from classical Noise with KEMs, while maintaining a
similar level of secrecy. This crate provides a safe Rust based implementation for the post-quantum
handshakes proposed by PQNoise - so that we can keep on benefitting from the clarity and formal
security guarantees of Noise even in post-quantum era.

## PQ Handshake Notation

Noise uses a simple pattern language for defining the handshake patterns. PQ patterns follow these same
rules, only substituting DH tokens with `ekem` and `skem` operations, which indicate sending of a ciphertext
that was encapsulated to the ephemeral/static key of the receiving party.

## Differences to PQNoise paper

* PQNoise presents the possibility to use different KEMs for ephemeral, initiator, and responder.
With Clatter the same KEM is used for both initiator and responder operations, while it is still
possible to configure a separate KEM for ephemeral use.
* PQNoise presents *SEEC*, a method for improving RNG security in bad randomness settings. Clatter
does not currently implement *SEEC*.

## Protocol Naming and Interoperability

Noise uses the protocol name as a basis for the handshake hash and for this reason it is important for
cross-implementation compatibility to have consistent naming schemes for the crypto primitives. For all
the classical ones Noise spec defines the naming but there is no absolute source for naming the PQ ones.

On top of this, there's also the fact that Kyber KEM was renamed to "ML-KEM" during the selection process
and some crypto crates still use the term "Kyber" while others have migrated to "ML-KEM". Clatter uses
whichever name the underlying crate has chosen to use.

Thus Clatter proposes and uses the following naming scheme:

| Primitive     | Protocol Name |
| ---           | ---           |
| Kyber 512     | `Kyber512`    |
| Kyber 768     | `Kyber768`    |
| Kyber 1024    | `Kyber1024`   |
| ML-KEM-512    | `MLKEM512`    |
| ML-KEM-768    | `MLKEM768`    |
| ML-KEM-1024   | `MLKEM1024`   |

Clatter also includes the possibility to pick different KEMs for ephemeral and static operations. If the
same KEM is used for both, the name of the KEM is simply placed in the protocol name in place of the DH algorithm.

Examples:

```text
Noise_pqNN_Kyber512_ChaChaPoly_BLAKE2s
Noise_pqNN_MLKEM512_ChaChaPoly_BLAKE2s
```

If, however, a different KEM is used for ephemeral and static operations, the resulting name will include both
KEMs joined together with a `+` symbol - ephemeral KEM first.

Examples:

```text
Noise_pqNN_Kyber512+Kyber1024_ChaChaPoly_BLAKE2s
Noise_pqNN_MLKEM512+Kyber768_ChaChaPoly_BLAKE2s
```

## Clatter hybrid handshakes

Clatter provides ready-made hybrid handshake types. Below is the formal specification of those handshake mechanisms while
the [crate documentation](https://docs.rs/clatter/latest/clatter/) provides practical details.

### [`HybridHandshake`](https://docs.rs/clatter/latest/clatter/type.HybridHandshake.html)

A *true hybrid* handshake which combines both DH and KEM operations. This handshake type accepts handshake patterns with
both DH and KEM operations and mixes the results of both exchanges in a single *symmetric state* containing the session
keys and hash, achieving true hybrid security against quantum threats while preserving the established safety guarantees
of classic algorithms - all with minimal effect to the number of round trips per handshake!

Clatter provides hybrid versions of the most commonly used Noise handshake patterns in the [`handshakepattern`](https://docs.rs/clatter/latest/clatter/handshakepattern/index.html)
module. These hybrid pattern variables are named as `noise_hybrid_<pattern>_...` and are essentially combined versions of the respective
NQ and PQ handshake patterns. Each handshake interaction will complete the operations of both the NQ and PQ patterns and the hybrid
pattern is constructed in a way which preserves the relative ordering of `DH` and `KEM` operations with respect to key material transmissions.

#### Tokens `e` and `s` handling

Handshake pattern tokens `e` and `s` require special handling for sending/receiving both the DH and KEM public keys.
Clatter will always place the public DH key first in the message buffer, followed by the public KEM key. All the related
`mix_hash` and `mix_key` operations are also conducted in the same order.

#### Hybrid protocol naming scheme

If a hybrid handshake uses the same KEM for both ephemeral and static operations, the handshake name will have the following format:

```text
Noise_hybrid<pattern>_<DH>+<KEM>_<cipher>_<hash>
```

If, however, a different KEM is used for ephemeral and static operations, the resulting name will include both KEMs joined
together with an additional `+` symbol - ephemeral KEM first:

```text
Noise_hybrid<pattern>_<DH>+<EKEM>+<SKEM>_<cipher>_<hash>
```

Examples:

```text
Noise_hybridNN_X25519+MLKEM512_ChaChaPoly_BLAKE2s
Noise_hybridNN_X25519+MLKEM512+MLKEM1024_ChaChaPoly_BLAKE2s
```

### [`HybridDualLayerHandshake`](https://docs.rs/clatter/latest/clatter/struct.HybridDualLayerHandshake.html)

An *outer-encrypts-inner* style handshake type which first completes the outer handshake and then uses the
resulting transport encryption to encrypt the inner handshake exchange. The handshakes are also cryptographically
bound together so that the final transport keys will derive entropy from both handshakes.

Once the outer handshake finishes, the inner handshake completes
the following Noise protocol steps:

* `MixHash("clatter.hybrid_dual_layer.outer")`
* `MixKeyAndHash(h_outer)`

Where `h_outer` is the resulting handshake hash from the finalized outer handshake.

### [`DualLayerHandshake`](https://docs.rs/clatter/latest/clatter/struct.DualLayerHandshake.html)

An *outer-encrypts-inner* style handshake type which first completes the outer handshake and then uses the
resulting transport encryption to encrypt the inner handshake exchange. The handshakes are not cryptographically bound and
the final transport keys only derive entropy from the inner handshake.

**Warning:** Use this handshake type only if you know what you are doing and absolutely require the handshake layers to remain independent.

## Verification

Clatter is verified by:

* Unit tests
* [Smoke tests](tests/)
* [Fuzzing](fuzz/)
* [Cacophony](https://github.com/haskell-cryptography/cacophony) and [Snow](https://github.com/mcginty/snow) test vectors
  * Supported pre-made handshake patterns verified
  * Test harness in [vectors/](vectors/)

## Changelog

Please see the [releases](https://github.com/jmlepisto/clatter/releases) page
