Threat Model
This document records the security assumptions, in-scope threats, and explicit non-goals for PostQuantum.Hybrid.
Assumptions
- The host OS, .NET runtime, and
System.Security.Cryptography(.NET 10) /BouncyCastle.Cryptography(.NET 8) packages are not compromised. - The system RNG (
System.Security.Cryptography.RandomNumberGenerator, and BouncyCastle'sSecureRandomwhich delegates to it on .NET) returns uniformly random bytes. - The caller's process does not leak private-key bytes through application logging, swap files, telemetry, or crash dumps.
- The caller follows the library's
IDisposablecontract.
Adversary model
We consider three adversaries:
Classical adversary (today)
- Polynomial-time classical computation.
- Read/modify network traffic.
- May obtain ciphertexts and signatures freely.
- May obtain public keys freely.
- May NOT obtain private keys.
Our defense: standard cryptographic security of X25519 + ML-KEM-768 and Ed25519 + ML-DSA-65. The hybrid construction here gives at least the security of the stronger of the two primitives.
Quantum adversary (future)
- Cryptographically-relevant quantum computer (CRQC).
- Same network capabilities as the classical adversary.
- May have already captured past ciphertexts ("harvest now, decrypt later").
Our defense: ML-KEM-768 and ML-DSA-65 are designed to resist quantum attack at NIST Level 3 (~AES-192 equivalent). The classical components add no security against this adversary, but they are kept for defense in depth against the next bullet.
Cryptanalytic-break adversary
- One of the four primitives is broken (e.g. a new attack reduces ML-KEM security below useful levels, or an X25519 implementation flaw is discovered).
Our defense: as long as at least one primitive in each family remains unbroken, the construction is secure. This is the entire point of going hybrid.
In-scope threats (we protect against these)
- Eavesdropping on KEM ciphertexts. Recovering the shared secret requires breaking both X25519 and ML-KEM-768.
- Tampering with KEM ciphertexts. Either ciphertext component being altered produces a different combined secret on the receiver side, so any AEAD downstream fails to decrypt.
- Signature forgery. Forging a hybrid signature requires forging both Ed25519 and ML-DSA-65, which requires breaking the underlying primitive (or stealing the private key).
- Cross-algorithm confusion. The algorithm-id byte in every wire artifact is checked on import/verify so blobs of mismatched types cannot be confused.
- Length confusion. All wire artifacts have fixed sizes and are length- checked on import.
- Implicit rejection on malformed KEM ciphertexts. Per FIPS 203, ML-KEM Decapsulate never throws on a bad ciphertext — it returns a pseudorandom secret. The combined hybrid secret will then differ from the sender's, so authenticated decryption fails naturally.
- Sensitive-data lingering in memory. All private-key types implement
IDisposableand zero their buffers on dispose.
Out-of-scope threats (NOT protected against)
- Private-key compromise. If an attacker reads a private key out of process memory, a file, or a backup, all past and future ciphertexts and signatures under that key are compromised. The library cannot prevent this; use a KMS / HSM in high-stakes deployments.
- Side-channel attacks. The library does not implement constant-time comparisons or memory-access patterns beyond what the underlying primitives provide. Timing, cache, electromagnetic, and power analysis attacks are out of scope.
- Harvest-now-decrypt-later on classical-only ciphertexts. If you only just now migrated from classical-only cryptography to PostQuantum.Hybrid, ciphertexts captured before the migration remain vulnerable to future quantum attack. The library cannot help you retroactively.
- Protocol-level attacks. Replay, freshness, identity binding, key rotation, transcript binding across multiple messages — all are the responsibility of the calling protocol. The library provides primitives, not protocols.
- Compromised RNG. Generating keys with a broken RNG yields broken keys. We have no defense against this at the library layer.
- Supply-chain compromise of dependencies. Mitigated via NuGet package signing and (planned) reproducible builds; not eliminated.
Operational guidance
These are not threats so much as recommended postures:
- Rotate keys. A 1- to 2-year rotation cadence limits the blast radius of an undetected key compromise. KEM ephemeral keys are already rotated per-encapsulation; long-lived static keys are the concern.
- Bind context. When you derive symmetric keys from a KEM shared secret,
use HKDF with a context-specific
infoparameter (seesamples/SecureMessenger) so the same KEM exchange can't be replayed in a different application context. - Always include AEAD over the message. Never use a KEM shared secret directly as plaintext or as a MAC key without an AEAD construction (AES-GCM, ChaCha20-Poly1305).
- Verify before decrypting. When combining sign-then-encrypt, verify
the signature before running KEM decapsulation. See
samples/SecureMessengerfor the canonical layout.
What we will do on a vulnerability disclosure
See SECURITY.md for the disclosure process.
If a vulnerability is found that breaks one of the four primitives:
- We release a patch version with new algorithm identifiers that opt into
a stronger combination (e.g.
X25519MlKem1024or a different PQ KEM). - The old algorithm identifier remains parseable (so existing keys still work) but is marked deprecated.
- A migration tool helps callers re-encrypt or re-sign their stored data under the new identifier.