Skip to content

Latest commit

 

History

History
570 lines (444 loc) · 23.8 KB

File metadata and controls

570 lines (444 loc) · 23.8 KB

Noise Protocol Patterns Reference

Version: 0.9.0 Last Updated: 2026-04-25

Overview

This document lists all Noise Protocol patterns implemented in NoisePQC++, including:

  • Classical patterns (57): Based on the Noise Protocol Framework Specification (Revision 34)
  • Post-Quantum (PQ) patterns (13): Using KEM (Key Encapsulation Mechanism) for quantum resistance
  • Hybrid Forward Secrecy (HFS) patterns (12): Combining DH and KEM for defense-in-depth

Pattern Notation

  • <- s or -> s: Pre-message patterns (keys known before handshake)
  • -> e, es: Initiator sends ephemeral key and performs DH
  • <- e, ee: Responder sends ephemeral key and performs DH

Classical Tokens (DH-based)

  • e: Ephemeral key generation/transmission
  • s: Static key transmission (encrypted after shared secret established)
  • ee: DH between ephemeral keys
  • es: DH between ephemeral-static keys
  • se: DH between static-ephemeral keys
  • ss: DH between static keys
  • psk: Pre-shared symmetric key mixing

Post-Quantum Tokens (KEM-based)

  • ekem: KEM encapsulation to remote ephemeral key (replaces ee in PQ patterns)
  • skem: KEM encapsulation to remote static key (replaces es/se/ss in PQ patterns)

Hybrid Forward Secrecy Tokens

  • e1: Additional ephemeral KEM key generation/transmission
  • ekem1: KEM encapsulation to remote e1 key (provides additional forward secrecy)

Implemented Patterns

One-Way Patterns (Section 7.4)

Single-message patterns for scenarios where only one party sends data.

Pattern Pre-Messages Messages Use Case
N <- s -> e, es Anonymous sender, known responder (e.g., querying a server)
K -> s, <- s -> e, es, ss Known sender and responder (e.g., cached credentials)
X <- s -> e, es, s, ss Sender authenticates to known responder

Security Properties:

  • N: Provides encryption and forward secrecy, but no sender authentication
  • K: Provides mutual authentication and forward secrecy
  • X: Provides sender authentication and forward secrecy

Fundamental Interactive Patterns (Section 7.5)

Two or three message patterns for full interactive handshakes.

Patterns with No Pre-Messages

Pattern Messages Authentication Use Case
NN -> e
<- e, ee
None → None Fully anonymous (e.g., Tor-like)
NX -> e
<- e, ee, s, es
None → Responder Anonymous initiator learns responder identity
XN -> e
<- e, ee
-> s, se
Initiator → None Initiator authenticates to anonymous responder
XX -> e
<- e, ee, s, es
-> s, se
Initiator → Responder Full mutual authentication (most common)
IN -> e, s
<- e, ee, se
Initiator → None Immediate initiator authentication
IX -> e, s
<- e, ee, se, s, es
Initiator → Responder Immediate mutual authentication

Patterns with Initiator Pre-Message -> s

Pattern Pre-Messages Messages Authentication Use Case
KN -> s -> e
<- e, ee, se
Known Initiator → None Server knows client's static key
KK -> s, <- s -> e, es, ss
<- e, ee, se
Initiator ↔ Responder Both know each other's keys (cached)
KX -> s -> e
<- e, ee, se, s, es
Known Initiator → Responder Client known to server, server authenticates

Patterns with Responder Pre-Message <- s

Pattern Pre-Messages Messages Authentication Use Case
NK <- s -> e, es
<- e, ee
None → Known Responder Client knows server's public key
XK <- s -> e, es
<- e, ee
-> s, se
Initiator → Known Responder Server's key pinned, client authenticates
IK <- s -> e, es, s, ss
<- e, ee, se
Initiator → Known Responder Immediate client auth to known server

Pattern Selection Guide

By Authentication Requirements

Need Recommended Patterns
No authentication NN, pqNN, NNhfs
Server authentication only NK, NX, pqNK, pqNX, NKhfs, NXhfs
Client authentication only KN, XN, IN, pqKN, pqXN, pqIN
Mutual authentication XX, KK, IK, IX, pqXX, pqKK, XXhfs, KKhfs
Pre-shared keys on both sides KK, K, or any PSK pattern
One-way message N, K, X, pqN
Delayed static key reveal Use deferred patterns (NK1, XX1, etc.)
Quantum resistance (pure PQ) pqXX, pqIK, pqNK (KEM-only)
Quantum + classical safety XXhfs, IKhfs, NKhfs (DH + KEM hybrid)

By Message Count

Messages Patterns
1 N, K, X
2 NN, NK, KN, KK, NX, KX, IN, IK, IX
3 XN, XK, XX

By Use Case

Use Case Pattern Reason
Web TLS-like (most common) XX Mutual authentication, no pre-shared keys
Client knows server's key NK or XK Simpler, prevents MITM if key is correct
Server knows client's key KN or KX Useful for returning clients
Both have cached keys KK Minimal handshake, maximum security
Anonymous sender to server N Single message, forward secrecy
IoT device to server IK Quick mutual auth with known server
Tor-like anonymity NN No identity revealed by either party
Quantum-safe communications pqXX Post-quantum key exchange
Future-proof security XXhfs Hybrid protection against quantum threats
High-security environments KKhfs Both keys known + hybrid protection
Long-term data protection pqIK, IKhfs Immediate auth + quantum resistance

Security Considerations

Forward Secrecy

All patterns provide forward secrecy (via ephemeral keys), meaning:

  • Past messages remain secure even if long-term keys are compromised
  • Ephemeral keys are destroyed after handshake

Identity Hiding

Pattern Category Initiator Identity Responder Identity
N, NN, NK, NX Hidden Varies
K, KN, KK, KX Known (pre-message) Varies
X, XN, XK, XX Encrypted in handshake Varies
I-patterns Encrypted in first msg Varies

Resistance to Key Compromise

  • Patterns with ss (static-static DH): More resistant to key compromise
  • Patterns with pre-messages: Vulnerable if those keys are compromised before handshake

Deferred Patterns (Section 9.4)

Deferred patterns delay static key transmission to later messages for improved privacy.

Pattern Pre-Messages Messages Use Case
NK1 <- s -> e
<- e, ee, es
NK with responder static delayed
NX1 -> e
<- e, ee, s
-> es
NX with responder static delayed, es deferred
X1N -> e
<- e, ee
-> s, se
XN variant (same as XN)
X1K <- s -> e, es
<- e, ee
-> s, se
XK with initiator static delayed
XK1 <- s -> e
<- e, ee, es
-> s, se
XK with responder DH delayed
X1K1 <- s -> e
<- e, ee, es
-> s, se
XK with both delays
X1X -> e
<- e, ee, s, es
-> s, se
XX variant
XX1 -> e
<- e, ee, s
-> es, s, se
XX with responder DH delayed
X1X1 -> e
<- e, ee, s
-> es, s, se
XX with both delays
K1N -> s -> e
<- e, ee
-> se
KN with initiator DH delayed
K1K -> s, <- s -> e, es
<- e, ee
-> se
KK with initiator DH delayed
KK1 -> s, <- s -> e
<- e, ee, se, es
KK with responder DH delayed
K1K1 -> s, <- s -> e
<- e, ee, es
-> se
KK with both delays
K1X -> s -> e
<- e, ee, s, es
-> se
KX with initiator DH delayed
KX1 -> s -> e
<- e, ee, se, s
-> es
KX with responder DH delayed
K1X1 -> s -> e
<- e, ee, s
-> se, es
KX with both delays
I1N -> e, s
<- e, ee
-> se
IN with initiator DH delayed
I1K <- s -> e, es, s
<- e, ee
-> se
IK with initiator DH delayed
IK1 <- s -> e, s
<- e, ee, se, es
IK with responder DH delayed
I1K1 <- s -> e, s
<- e, ee, es
-> se
IK with both delays
I1X -> e, s
<- e, ee, s, es
-> se
IX with initiator DH delayed
IX1 -> e, s
<- e, ee, se, s
-> es
IX with responder DH delayed
I1X1 -> e, s
<- e, ee, s
-> se, es
IX with both delays

Deferred Pattern Benefits:

  • Improved identity hiding by delaying static key transmission
  • More flexible key agreement timing
  • Better protection against active attacks during early handshake

PSK (Pre-Shared Key) Patterns

PSK patterns incorporate pre-shared symmetric keys for additional security.

One-Way PSK Patterns

Pattern Pre-Messages Messages PSK Location
Npsk0 <- s -> psk, e, es Start of message 1
Kpsk0 -> s, <- s -> psk, e, es, ss Start of message 1
Xpsk1 <- s -> e, es, s, ss, psk End of message 1

Interactive PSK Patterns

Pattern Base Messages PSK Location
NNpsk0 NN 2 After Token 0 (start of msg 1)
NNpsk2 NN 2 After ee (end of msg 2)
NKpsk0 NK 2 Start of msg 1
NKpsk2 NK 2 End of msg 2
NXpsk2 NX 2 End of msg 2
XNpsk3 XN 3 End of msg 3
XKpsk3 XK 3 End of msg 3
XXpsk3 XX 3 End of msg 3
KNpsk0 KN 2 Start of msg 1
KNpsk2 KN 2 End of msg 2
KKpsk0 KK 2 Start of msg 1
KKpsk2 KK 2 End of msg 2
KXpsk2 KX 2 End of msg 2
INpsk1 IN 2 After first DH (after se in msg 1)
INpsk2 IN 2 End of msg 2
IKpsk1 IK 2 After first DH (after es in msg 1)
IKpsk2 IK 2 End of msg 2
IXpsk2 IX 2 End of msg 2

PSK Pattern Benefits:

  • Defense against future quantum computer attacks (when combined with PQ DH)
  • Additional layer of authentication
  • Useful for known-device scenarios
  • Can mitigate key compromise

Post-Quantum (PQ) Patterns

Post-Quantum patterns replace DH operations with KEM (Key Encapsulation Mechanism) operations using ML-KEM (CRYSTALS-Kyber). These patterns provide resistance against quantum computer attacks.

Protocol String Format

Noise_pqXX_M768_ChaChaPoly_SHA256
      ^^^^  ^^^^
      |     |
      |     +-- KEM algorithm: M512, M768, or M1024
      +-------- PQ pattern name (prefixed with "pq")

PQ One-Way Patterns

Pattern Pre-Messages Messages Classical Equivalent
pqN <- s -> e, skem N

PQ Interactive Patterns

Pattern Pre-Messages Messages Classical Equivalent Use Case
pqNN -> e
<- e, ekem
NN Fully anonymous, quantum-resistant
pqNK <- s -> e, skem
<- e, ekem
NK Client knows server's KEM key
pqNX -> e
<- e, ekem, s, skem
NX Quantum-resistant server auth
pqXN -> e
<- e, ekem
-> s, skem
XN Quantum-resistant client auth
pqXK <- s -> e, skem
<- e, ekem
-> s, skem
XK Client authenticates to known server
pqXX -> e
<- e, ekem, s, skem
-> s, skem
XX Full mutual auth (most common PQ)
pqKN -> s -> e
<- e, ekem, skem
KN Server knows client's KEM key
pqKK -> s, <- s -> e, skem
<- e, ekem, skem
KK Both have cached KEM keys
pqKX -> s -> e
<- e, ekem, skem, s, skem
KX Client known, server authenticates
pqIN -> e, s
<- e, ekem, skem
IN Immediate client auth
pqIK <- s -> e, skem, s
<- e, ekem, skem
IK Immediate auth to known server
pqIX -> e, s
<- e, ekem, skem, s, skem
IX Immediate mutual auth

PQ Token Semantics

Token Operation Direction
ekem Encapsulate to remote ephemeral Writer encapsulates to reader's e
skem Encapsulate to remote static Writer encapsulates to reader's s

Key Differences from Classical:

  • e token: Sends KEM public key (1184 bytes for M768) instead of DH public key
  • ekem replaces ee: Encapsulates to remote ephemeral
  • skem replaces es, se, ss: Encapsulates to remote static

PQ Pattern Example

import noise;
using namespace Noise;

// Create PQ protocol
Protocol protocol("Noise_pqXX_M768_ChaChaPoly_BLAKE2s");
// Or: Protocol protocol(pqXX, M768, ChaChaPoly, BLAKE2s);

// Generate KEM keypairs
auto aliceStatic = protocol.dh.GenerateKeypair();  // ML-KEM-768 keypair
auto bobStatic = protocol.dh.GenerateKeypair();

// Configure handshakes (same API as classical)
HandshakeConfig aliceCfg{.protocol = protocol, .isInitiator = true, .localStatic = aliceStatic};
HandshakeConfig bobCfg{.protocol = protocol, .isInitiator = false, .localStatic = bobStatic};

// Execute pqXX handshake (3 messages, same as XX)
HandshakeState aliceHs(aliceCfg), bobHs(bobCfg);

auto msg1 = aliceHs.WriteMessage({});      // -> e
bobHs.ReadMessage(msg1);

auto msg2 = bobHs.WriteMessage({});        // <- e, ekem, s, skem
aliceHs.ReadMessage(msg2);

auto msg3 = aliceHs.WriteMessage({});      // -> s, skem
bobHs.ReadMessage(msg3);

// Handshake complete - quantum-resistant transport

Hybrid Forward Secrecy (HFS) Patterns

HFS patterns combine classical DH with KEM for defense-in-depth. They provide:

  • Forward secrecy from both DH and KEM
  • Protection if either primitive is broken
  • "Harvest now, decrypt later" attack resistance

Protocol String Format

Noise_XXhfs_25519+M768_ChaChaPoly_SHA256
      ^^^^^  ^^^^^^^^^^
      |      |
      |      +-- Combined DH+KEM: 25519+M768, 448+M1024, etc.
      +--------- HFS pattern name (suffixed with "hfs")

HFS Interactive Patterns

Pattern Messages Classical Base Use Case
NNhfs -> e, e1
<- e, e1, ee, ekem1
NN Anonymous hybrid
NKhfs -> e, e1, es
<- e, e1, ee, ekem1
NK Hybrid server auth
NXhfs -> e, e1
<- e, e1, ee, ekem1, s, es
NX Hybrid responder auth
XNhfs -> e, e1
<- e, e1, ee, ekem1
-> s, se
XN Hybrid initiator auth
XKhfs -> e, e1, es
<- e, e1, ee, ekem1
-> s, se
XK Hybrid mutual (known server)
XXhfs -> e, e1
<- e, e1, ee, ekem1, s, es
-> s, se
XX Hybrid mutual auth
KNhfs -> e, e1
<- e, e1, ee, ekem1, se
KN Hybrid (known initiator)
KKhfs -> e, e1, es, ss
<- e, e1, ee, ekem1, se
KK Hybrid (both known)
KXhfs -> e, e1
<- e, e1, ee, ekem1, se, s, es
KX Hybrid (known initiator)
INhfs -> e, e1, s
<- e, e1, ee, ekem1, se
IN Immediate hybrid initiator
IKhfs -> e, e1, es, s, ss
<- e, e1, ee, ekem1, se
IK Immediate hybrid mutual
IXhfs -> e, e1, s
<- e, e1, ee, ekem1, se, s, es
IX Immediate hybrid responder

HFS Token Semantics

Token Operation Key Type
e DH ephemeral key X25519 or X448
e1 KEM ephemeral key ML-KEM-512/768/1024
ee DH between ephemerals DH shared secret
ekem1 KEM encapsulation to e1 KEM shared secret

Key Insight: HFS patterns mix both DH and KEM secrets into the chaining key, ensuring security even if one primitive is broken.

HFS Pattern Example

import noise;
using namespace Noise;

// Create HFS protocol (DH + KEM)
Protocol protocol("Noise_XXhfs_25519+M768_ChaChaPoly_BLAKE2s");
// Or: Protocol protocol(XXhfs, X25519, M768, ChaChaPoly, BLAKE2s);

// Generate static keypairs (DH only for static keys in XXhfs)
auto aliceStatic = protocol.dh.GenerateKeypair();
auto bobStatic = protocol.dh.GenerateKeypair();

// Configure handshakes
HandshakeConfig aliceCfg{.protocol = protocol, .isInitiator = true, .localStatic = aliceStatic};
HandshakeConfig bobCfg{.protocol = protocol, .isInitiator = false, .localStatic = bobStatic};

// Execute XXhfs handshake
HandshakeState aliceHs(aliceCfg), bobHs(bobCfg);

auto msg1 = aliceHs.WriteMessage({});      // -> e, e1 (DH + KEM ephemerals)
bobHs.ReadMessage(msg1);

auto msg2 = bobHs.WriteMessage({});        // <- e, e1, ee, ekem1, s, es
aliceHs.ReadMessage(msg2);

auto msg3 = aliceHs.WriteMessage({});      // -> s, se
bobHs.ReadMessage(msg3);

// Hybrid-secured transport

Pattern Comparison

Classical vs PQ vs HFS

Aspect Classical (XX) Post-Quantum (pqXX) Hybrid (XXhfs)
Ephemeral size 32 bytes 1184 bytes (M768) 32 + 1184 bytes
Key exchange DH only KEM only DH + KEM
Quantum safe
Classical safe ✅ (assumed)
Message overhead Low Higher Highest
Use case General purpose Quantum preparation Defense-in-depth

Protocol String Examples

Classical: Noise_XX_25519_ChaChaPoly_BLAKE2s
PQ:        Noise_pqXX_M768_ChaChaPoly_BLAKE2s
HFS:       Noise_XXhfs_25519+M768_ChaChaPoly_BLAKE2s

Implementation Status

Fully Implemented (82 patterns):

Classical Patterns (57)

  • One-way: N, K, X (3 patterns)
  • Fundamental Interactive: NN, NK, NX, KN, KK, KX, XN, XK, XX, IN, IK, IX (12 patterns)
  • Deferred: NK1, NX1, X1N, X1K, XK1, X1K1, X1X, XX1, X1X1, K1N, K1K, KK1, K1K1, K1X, KX1, K1X1, I1N, I1K, IK1, I1K1, I1X, IX1, I1X1 (21 patterns)
  • PSK: Npsk0, Kpsk0, Xpsk1, NNpsk0, NNpsk2, NKpsk0, NKpsk2, NXpsk2, XNpsk3, XKpsk3, XXpsk3, KNpsk0, KNpsk2, KKpsk0, KKpsk2, KXpsk2, INpsk1, INpsk2, IKpsk1, IKpsk2, IXpsk2 (21 patterns)

Post-Quantum Patterns (13)

  • One-way: pqN (1 pattern)
  • Interactive: pqNN, pqNK, pqNX, pqXN, pqXK, pqXX, pqKN, pqKK, pqKX, pqIN, pqIK, pqIX (12 patterns)

Hybrid Forward Secrecy Patterns (12)

  • Interactive: NNhfs, NKhfs, NXhfs, XNhfs, XKhfs, XXhfs, KNhfs, KKhfs, KXhfs, INhfs, IKhfs, IXhfs (12 patterns)

Future Extensions:

  • Fallback patterns (maybe)
  • Additional deferred PQ/HFS variants

Testing Matrix

All 82 patterns are fully tested with comprehensive test coverage (200+ test cases, 500+ assertions).

Pattern Unit Test Integration Test Interop Test File Location
One-Way Patterns
N test_handshakestate.cpp:1209
K test_handshakestate.cpp:1223
X test_handshakestate.cpp:1237
Two-Message Interactive
NN test_handshakestate.cpp (complete)
NK test_handshakestate.cpp (complete)
NX test_handshakestate.cpp:1251
KN test_handshakestate.cpp:1265
KK test_handshakestate.cpp (complete)
KX test_handshakestate.cpp:1279
IN test_handshakestate.cpp:1321
IK test_handshakestate.cpp:1335
IX test_handshakestate.cpp:1349
Three-Message Interactive
XN test_handshakestate.cpp:1293
XK test_handshakestate.cpp:1307
XX test_handshakestate.cpp (complete)
Deferred Patterns (21 total)
All deferred test_handshakestate.cpp (lines 1400-1700)
PSK Patterns (21 total)
All PSK test_handshakestate.cpp (lines 1770-2100)
Post-Quantum Patterns (13 total)
pqN test_noise_pq.cpp
pqNN, pqNK, pqNX test_noise_pq.cpp
pqXN, pqXK, pqXX test_noise_pq.cpp
pqKN, pqKK, pqKX test_noise_pq.cpp
pqIN, pqIK, pqIX test_noise_pq.cpp
HFS Patterns (12 total)
NNhfs, NKhfs, NXhfs test_hfs.cpp
XNhfs, XKhfs, XXhfs test_hfs.cpp
KNhfs, KKhfs, KXhfs test_hfs.cpp
INhfs, IKhfs, IXhfs test_hfs.cpp

Test Coverage Details:

  • ✅ Pattern-specific handshake execution
  • ✅ Key configuration validation
  • ✅ Message flow verification
  • ✅ Completion status checks
  • ✅ Handshake hash matching
  • ✅ Cipher state generation
  • ✅ Error handling (truncation, out-of-order, size limits)
  • ✅ Observer pattern callbacks
  • ✅ Prologue handling
  • ✅ Multiple algorithm combinations (X448, AESGCM, BLAKE2b)
  • ✅ KEM encapsulation/decapsulation (ML-KEM-512/768/1024)
  • ✅ Hybrid DH+KEM key mixing

Running Tests:

# Run all handshake tests (classical patterns)
./tests/test_handshakestate

# Run Post-Quantum pattern tests
./tests/test_noise_pq

# Run Hybrid Forward Secrecy tests
./tests/test_hfs

# Run specific pattern tests
./tests/test_handshakestate "[oneway]"      # All one-way patterns
./tests/test_handshakestate "[interactive]"  # All interactive patterns
./tests/test_handshakestate "[deferred]"     # All 21 deferred patterns
./tests/test_handshakestate "[psk]"          # All 21 PSK patterns
./tests/test_handshakestate "[xx]"           # XX pattern only
./tests/test_noise_pq "[pqxx]"               # pqXX pattern only
./tests/test_hfs "[xxhfs]"                   # XXhfs pattern only

# List all test cases
./tests/test_handshakestate --list-tests
./tests/test_noise_pq --list-tests
./tests/test_hfs --list-tests

References

  1. Noise Protocol Framework Specification - Official specification (Revision 34+)
  2. Noise Explorer - Pattern analysis and visualization
  3. nyquist (Go) - Reference implementation
  4. WireGuard - Uses Noise IK pattern

Quick Start

Example: XX Handshake

import noise;
using namespace Noise;

// Create protocol: Noise_XX_X25519_ChaChaPoly_SHA256
Protocol protocol(XX, X25519, ChaChaPoly, SHA256);

// Generate static keys
auto aliceStatic = protocol.dh.GenerateKeypair();
auto bobStatic = protocol.dh.GenerateKeypair();

// Configure handshake states
HandshakeConfig aliceCfg{.protocol = protocol, .isInitiator = true, .localStatic = aliceStatic};
HandshakeConfig bobCfg{.protocol = protocol, .isInitiator = false, .localStatic = bobStatic};

HandshakeState aliceHs(aliceCfg);
HandshakeState bobHs(bobCfg);

// Execute 3-message handshake
auto msg1 = aliceHs.WriteMessage({'h', 'e', 'l', 'l', 'o'});
auto recv1 = bobHs.ReadMessage(msg1);

auto msg2 = bobHs.WriteMessage({});
aliceHs.ReadMessage(msg2);

auto msg3 = aliceHs.WriteMessage({});
bobHs.ReadMessage(msg3);

// Handshake complete! Both have cipher states for transport encryption
auto [aliceTx, aliceRx] = *aliceHs.GetStatus().cipherStates;

See examples/example_test.cpp for complete working examples.


Last Updated: 2026-04-25 Pattern Count: 82 patterns (57 classical + 13 PQ + 12 HFS, all tested) Test Coverage: 200+ test cases, 500+ assertions Specification Version: Revision 34+ (with PQNoise and HFS extensions)