Post-quantum algorithm policy
graph TD
OP["Operation with a PQ part"]
REC{"Does the guideline recommend the algorithm?"}
KIND{"Does the operation create new data?"}
PURE{"CryptoMode.PostQuantum?"}
FLAG{"Exemption set in PostQuantumConfig.Exemptions?"}
RUN["Operation runs"]
EVT["PolicyDeviation event, then the operation runs"]
ERR["CryptographicException naming the guideline section and the exemption"]
OP --> REC
REC -- "yes" --> RUN
REC -- "no" --> PURE
PURE -- "yes" --> FLAG
PURE -- "no" --> KIND
KIND -- "yes: generate, sign, encapsulate, encrypt" --> FLAG
KIND -- "no: verify, decapsulate, decrypt" --> EVT
FLAG -- "yes" --> EVT
FLAG -- "no" --> ERR
Figure: Recommended algorithms simply run. Other algorithms create new data only with an exemption.
Existing data stays verifiable and readable without an exemption, except in PostQuantum mode. Every
deviation raises the PolicyDeviation event.
For post-quantum (PQ) algorithms, the library enforces the recommendations of Technical Guideline BSI TR-02102-1, Cryptographic Mechanisms: Recommendations and Key Lengths, version 2026-01, published by the German Federal Office for Information Security (BSI), as its default. Algorithms that the guideline doesn't recommend are still available, because standards and peers require them. But your app uses them only if it explicitly allows them at startup.
Key features
- Defaults that follow BSI TR-02102-1 (2026-01):
PostQuantumConfig.Policynames the guideline. Unless you specify otherwise, the library only creates data with recommended algorithms. - Exemptions in
PostQuantumConfig.Exemptionsfor three rules: pure PQ algorithms, reduced parameter sets, and combiners that aren't recommended. - Existing data stays readable: Verifying, decapsulating, and decrypting with reduced parameter sets and nonrecommended combiners works without an exemption.
- The
PostQuantumConfig.PolicyDeviationevent fires for every use beyond the recommendation, so you can log it, count it, or reject it. - KeyCombine as defined in NIST SP 800-227 is the default for every hybrid key agreement in the library, and it's publicly available as
KeyCombiner.Combine.
Core concepts
How the guideline classifies each algorithm
The table separates three questions: What does the guideline recommend, what does the library implement, and what does the library allow without an exemption?
| Algorithm | BSI TR-02102-1 (2026-01) | In the library | Without an exemption |
|---|---|---|---|
| ML-DSA-65, ML-DSA-87, hedged variant, pure version | recommended, §5.3.4.2, Table 5.7, Remark 5.10 | implemented | allowed, combined with RSA or ECDSA |
| ML-DSA-44 | not recommended | implemented | key generation and signing blocked, verification allowed |
| ML-KEM-768, ML-KEM-1024 | recommended, §2.4.3, Table 2.7 | implemented | allowed, combined with a classical algorithm |
| ML-KEM-512 | not recommended | implemented | key generation and encapsulation blocked, decapsulation allowed |
| PQ signature only combined with a classical signature | recommended, §5.3.4 | implemented: hybrid certificates, CRLs, and requests; composite ML-DSA; hybrid CMS and XML signatures | allowed |
| PQ key encapsulation only combined with a classical algorithm | recommended, §2.4 | implemented: ECDH with ML-KEM, RSA-OAEP with ML-KEM, composite ML-KEM | allowed; for combiners, see below |
PQ algorithm on its own (CryptoMode.PostQuantum) | not recommended, §2.4 and §5.3.4 | implemented, for example for ML-DSA certificates as defined in RFC 9881 | every operation blocked, including verification |
| KeyCombine, NIST SP 800-227 Eq. (15), H = HKDF | recommended, §2.2, Table 2.1 | implemented, default | allowed |
| CatKDF, ETSI TS 103 744 | recommended, §2.2, Table 2.1 | not implemented | – |
The library's first combiner (HybridKeyCombiner.Version1) | not among the recommended combiners | readable | creation blocked, reading allowed |
| Composite ML-KEM combiner (SHA3-256) | not among the recommended combiners | implemented | encapsulation blocked, decapsulation allowed |
| SLH-DSA, LMS/HSS, XMSS/XMSS^MT | recommended, §5.3.4.1, §5.3.4.3 | not implemented | – |
| FrodoKEM, Classic McEliece | recommended, §2.4.1, §2.4.2 | not implemented | – |
| HKDF | recommended, Appendix B.1, Table B.1 | implemented, as H in KeyCombine | allowed |
| Argon2id for keys derived from passwords | recommended, Appendix B.1.2 | implemented, for backups of the key files | allowed |
Blocked means that the operation throws a CryptographicException. Allowed for a nonrecommended
algorithm means that the operation runs and raises the PolicyDeviation event.
Exemptions
PostQuantumConfig.Exemptions is a flags enumeration (PostQuantumExemptions). Each flag allows creating
new data under one rule that the guideline doesn't recommend:
| Flag | Allows | Basis |
|---|---|---|
PurePostQuantum | CryptoMode.PostQuantum with all operations: pure ML-DSA certificates and CRLs, pure ML-DSA signatures, encryption for pure ML-KEM recipients; also EnablePostQuantum(CryptoMode.PostQuantum) | §2.4, §5.3.4 |
ReducedParameterSets | key generation, signing, and encapsulation with ML-DSA-44 and ML-KEM-512, including in composite pairs | §5.3.4.2, Table 5.7; §2.4.3, Table 2.7 |
NonRecommendedCombiners | encapsulation to composite ML-KEM keys; creating hybrid data with HybridKeyCombiner.Version1; DeriveHybridKey and DeriveHybridKeyMaterial in Hybrid mode | §2.2, Table 2.1 |
Set the flags once when your app starts, before the first cryptographic operation. They apply to the whole process:
// The app issues ML-DSA certificates as defined in RFC 9881. PostQuantumConfig.Exemptions = PostQuantumExemptions.PurePostQuantum;
If the flag is missing, the CryptographicException names the guideline section, the recommended
alternative, and the flag. For ML-DSA-44, the message reads:
ML-DSA-44 is not recommended by BSI TR-02102-1 (2026-01), §5.3.4.2, Table 5.7; use ML-DSA-65 or ML-DSA-87. To create data with it anyway, permit it at startup with PostQuantumConfig.Exemptions |= PostQuantumExemptions.ReducedParameterSets. Verifying and decapsulating existing data needs no exemption.
The PolicyDeviation event
PostQuantumConfig.PolicyDeviation reports every use beyond the recommendation, right before the operation
runs. The PostQuantumPolicyEventArgs arguments describe the deviation:
| Property | Content |
|---|---|
Rule | the rule, named after the flag that allows it; exactly one flag is set |
Algorithm | the algorithm, for example ML-DSA-44, CryptoMode.PostQuantum, or Composite ML-KEM (SHA3-256) |
Operation | the operation, for example GenerateKey, Sign, or Verify; intended for logs, not a stable contract |
Reference | the guideline and section, for example BSI TR-02102-1 (2026-01), §5.3.4.2, Table 5.7 |
IsExempted | true if a flag allowed the use; false if it's allowed without a flag because it only verifies or opens existing data |
The handler runs synchronously on the operation's thread. If it throws, the operation stops and the caller receives that exception. This way, your app can even reject verifying old data that uses nonrecommended algorithms. Operations that fail because a flag is missing don't raise the event.
PostQuantumConfig.PolicyDeviation += (_, e) => Console.WriteLine($"{e.Algorithm} in {e.Operation} ({e.Reference}), exempted: {e.IsExempted}");
KeyCombine
A hybrid key agreement runs a PQ algorithm and a classical algorithm side by side and derives one key from both secrets. The key is meant to stay secure as long as either algorithm is secure. That only works if the combiner binds not just the secrets but also the ciphertexts and the public keys. For this purpose, the guideline recommends CatKDF and KeyCombine (§2.2, Table 2.1).
The library implements KeyCombine as defined in NIST SP 800-227, section 4.6.2, equation (15), and realizes the function H with HKDF-SHA256 (RFC 5869), as the guideline recommends:
- Input: the two secrets as key material; the lengths of the secrets, both ciphertexts, both public keys, and a domain separator as context. Each value is prefixed with its length, so no two inputs can concatenate to the same byte sequence.
- Domain separator: a fixed identifier of the construction, the names of both algorithms with their parameter sets, and the caller's context.
- Use:
HybridKeyAgreement(ECDH with ML-KEM),EncryptHybrid(RSA-OAEP with ML-KEM), andEncryptEcdhPquse KeyCombine by default.KeyCombiner.Combineis available for your own protocols.
HybridEncryptedData records the combiner in the data header, so data from an earlier version of the
library that used HybridKeyCombiner.Version1 can still be decrypted.
Limitations
- One guideline, not replaceable. The library only knows BSI TR-02102-1, version 2026-01. A new version of the guideline comes with a new version of the library, and the CHANGELOG then lists the changed rules.
- PQ algorithms only. The policy covers ML-DSA, ML-KEM, their combinations, and the combiners. The library doesn't check classical algorithms or their key sizes, such as RSA-2048 instead of RSA-3072. The policy doesn't affect calls without
CryptoModeand without a PQ key. - Building blocks for a single algorithm.
MLDsaKey,MLKemKey, and the provider methods (ICryptoProvider, for exampleSignMlDsaAsyncin Blazor WebAssembly) compute one algorithm on its own, as a building block for a combination. They check the parameter sets, not the mode. It's up to your app to make sure that such a building block works together with a classical algorithm in your protocol. - Dedicated keys for hybrid signatures. The guideline recommends generating keys for hybrid signatures only for that purpose and not reusing them for single signatures (§5.3.4). If you don't supply a key, the library generates a new ML-DSA key for each hybrid certificate. If you supply one yourself, for example through
X509CertificateBuilder.AlternativeKey, the library can't check whether you also use it elsewhere. - No substitute for an evaluation. The defaults implement the guideline's recommendations for algorithms and parameter sets. They aren't an approval or a certification of the library or of any app.
- PBKDF2 in PFX files. PKCS#12 doesn't support Argon2id, so PFX files derive their key with PBKDF2. See Keys and key storage.
- Process-wide flags.
Exemptionsapplies to all threads. A change while operations are running affects those operations in no defined order.