v151 · origin trial · webcrypto · post-quantum
Algorithm Updates in WebCrypto
A modernization of the Web Cryptography API: post-quantum algorithms (ML-KEM, hybrid PQ/classical KEMs, ML-DSA, SLH-DSA), modern AEAD ciphers (AES-OCB, ChaCha20-Poly1305), the SHA-3/Keccak family (SHA3 digests, cSHAKE, TurboSHAKE, KangarooTwelve, KMAC), and the Argon2 password KDF — plus new SubtleCrypto methods for key encapsulation (encapsulateKey/decapsulateKey and their -Bits forms), getPublicKey, and a static supports() capability check.
Chromium trunk reads the runtime feature WebCryptoPQC as status “stable” (runtime_enabled_features.json5, fetched 2026-10-06) and BCD records Chrome 155 for all six new members (experimental). The developer trial (Chrome 150, behind a flag) and the desktop origin trial (Chrome 151–154) have concluded. Every algorithm remains OPTIONAL to implement per the spec, and other engines’ support is partial — so feature-detection is still required:
- Chrome 155 and later: feature-detect with the static
SubtleCrypto.supports(operation, algorithm)before calling — algorithm availability varies by build and platform. - Chrome 151–154 (concluded): the “WebCrypto Additional Algorithms” desktop origin trial with public registration, at developer.chrome.com/origintrials. The origin-trial id
1379790335835635713and feature nameWebCryptoAdditionalAlgorithms202606were recorded from the chromestatus listing during the 2026-07-28 verification; neither appears in the chromestatus API response re-fetched 2026-10-06 nor in trunk runtime_enabled_features.json5, so both are reported as a historical record, unverified against current sources. - Chrome 150 (historical): developer trial behind
--enable-blink-features=WebCryptoPQC. - Serve over HTTPS — the partial interface is exposed with
[SecureContext]in Window and Worker contexts.
at a glance
| Shipped state | Chrome 155 — BCD records version_added: 155 for all six new members, status experimental (fetched 2026-10-06); Chromium trunk runtime flag reads “stable”. ChromeStatus (updated 2026-09-11) still lists “Chrome 151 — Origin trial” and lags the shipped state. |
|---|---|
| Origin trial | Concluded — desktop, Chrome 151–154, public registration (verified 2026-07-28). The recorded origin-trial id 1379790335835635713 and feature name WebCryptoAdditionalAlgorithms202606 do not appear in the chromestatus API response re-fetched 2026-10-06 — reported as historical record, unverified against current sources |
| Ship estimate | ChromeStatus records none (desktop milestone unset, status text “Proposed”, updated 2026-09-11); BCD records Chrome 155 (experimental). The two sources disagree and the page reports both rather than choosing |
| Interface | SubtleCrypto (partial), via crypto.subtle |
| Context | Secure contexts, Window and Worker |
| Runtime flag | WebCryptoPQC in runtime_enabled_features.json5 — status “stable” on trunk (fetched 2026-10-06) |
| Standards body | WICG — WebCrypto Modern Algorithms |
| ChromeStatus | 5198951632470016 — Algorithm Updates in WebCrypto |
Syntax
The update extends SubtleCrypto with four key-encapsulation methods (KEM support for ML-KEM), a public-key derivation helper, and a static feature-detection method. IDL from the WICG draft:
[SecureContext, Exposed=(Window,Worker)]
partial interface SubtleCrypto {
Promise<EncapsulatedKey> encapsulateKey(
AlgorithmIdentifier encapsulationAlgorithm,
CryptoKey encapsulationKey,
AlgorithmIdentifier sharedKeyAlgorithm,
boolean extractable,
sequence<KeyUsage> keyUsages
);
Promise<EncapsulatedBits> encapsulateBits(
AlgorithmIdentifier encapsulationAlgorithm,
CryptoKey encapsulationKey
);
Promise<CryptoKey> decapsulateKey(
AlgorithmIdentifier decapsulationAlgorithm,
CryptoKey decapsulationKey,
BufferSource ciphertext,
AlgorithmIdentifier sharedKeyAlgorithm,
boolean extractable,
sequence<KeyUsage> keyUsages
);
Promise<ArrayBuffer> decapsulateBits(
AlgorithmIdentifier decapsulationAlgorithm,
CryptoKey decapsulationKey,
BufferSource ciphertext
);
Promise<CryptoKey> getPublicKey(
CryptoKey key,
sequence<KeyUsage> keyUsages
);
static boolean supports(DOMString operation,
AlgorithmIdentifier algorithm,
optional [EnforceRange] unsigned long? length = null);
static boolean supports(DOMString operation,
AlgorithmIdentifier algorithm,
AlgorithmIdentifier additionalAlgorithm);
};
Source: WICG WebCrypto Modern Algorithms — Partial SubtleCrypto interface
enum KeyFormat { "raw-public", "raw-private", "raw-seed", "raw-secret",
"raw", "spki", "pkcs8", "jwk" };
enum KeyUsage { "encrypt", "decrypt", "sign", "verify", "deriveKey", "deriveBits",
"wrapKey", "unwrapKey",
"encapsulateKey", "encapsulateBits",
"decapsulateKey", "decapsulateBits" };
dictionary EncapsulatedKey {
CryptoKey sharedKey;
ArrayBuffer ciphertext;
};
dictionary EncapsulatedBits {
ArrayBuffer sharedKey;
ArrayBuffer ciphertext;
};
Source: WICG WebCrypto Modern Algorithms — Data types, Encapsulation dictionaries
| Dimension | Sourced fact |
|---|---|
| inputs | No source fact. sharedKey is a dictionary field, not a callable: it has no parameter list and a caller never passes it. It is set by the encapsulate algorithm, not by the caller. (The word sharedKey also names the sharedKeyAlgorithm/sharedKey local in encapsulateKey()/decapsulateKey(), but that is a different, same-named variable — see outputs.) |
| outputs | The draft sets it to the encapsulated shared secret. In encapsulateKey() (§3.2.1): “Let encapsulatedKey be a new EncapsulatedKey dictionary with sharedKey set to sharedKey and ciphertext set to the ciphertext field of encapsulatedBits.” The type differs by dictionary (§4): CryptoKey sharedKey in EncapsulatedKey (dfn), versus ArrayBuffer sharedKey in EncapsulatedBits (dfn). In encapsulateBits() the EncapsulatedBits result carries the raw bits: “Let result be the result of converting encapsulatedBits to an ECMAScript Object in realm, as defined by [WebIDL].” |
| errors | No source fact. A dictionary field raises nothing; the throw/reject sites belong to the six methods (§3.2.1–§3.2.5), not to the field. There is no field-level error prose in §4. |
| context | No source fact. The draft gives the two dictionaries no [SecureContext]/Exposed attribute and no context prose — they are plain data types. The [SecureContext, Exposed=(Window,Worker)] marker sits on the partial interface SubtleCrypto (§3), not on either dictionary, so it does not attach to sharedKey. |
| compatibility | No source fact. BCD api/SubtleCrypto.json carries no sharedKey key (only the six method keys); there is no compatibility datum for the field. |
| securityPrivacy | The field holds the shared secret, and the draft’s only statement about it is the §4 definition sentence: “The EncapsulatedKey dictionary represents an encapsulated key comprised of a sharedKey and a ciphertext.” There is no dedicated Security/Privacy Considerations section in the draft (no “security”/“privacy” heading exists), so beyond that definition sentence and the interface-level [SecureContext] there is no field-level security/privacy fact to cite. |
| Dimension | Sourced fact |
|---|---|
| inputs | No source fact as a field. As a dictionary member ciphertext is not callable and is set by the encapsulate algorithm. Separately, ciphertext is a BufferSource parameter to decapsulateKey()/decapsulateBits(), consumed per §3.2.3: “Let ciphertext be the result of getting a copy of the bytes held by the ciphertext parameter passed to the decapsulateKey() method.” (and the analogous decapsulateBits() step in §3.2.4). That is the parameter, not the dictionary field. |
| outputs | The draft sets it to the encapsulation ciphertext (the material sent to the recipient). In encapsulateKey() (§3.2.1): “Let encapsulatedKey be a new EncapsulatedKey dictionary with sharedKey set to sharedKey and ciphertext set to the ciphertext field of encapsulatedBits.” The type is the same in both dictionaries (§4): ArrayBuffer ciphertext in both EncapsulatedKey (dfn) and EncapsulatedBits (dfn). |
| errors | No source fact. A dictionary field raises nothing; there is no field-level error prose in §4. |
| context | No source fact. The two dictionaries carry no [SecureContext]/Exposed attribute and no context prose; the interface-level [SecureContext, Exposed=(Window,Worker)] does not attach to ciphertext. |
| compatibility | No source fact. BCD api/SubtleCrypto.json carries no ciphertext key; there is no compatibility datum for the field. |
| securityPrivacy | The field holds the public encapsulation ciphertext (transmitted, not secret), and the draft’s only statement about it is the §4 definition sentence: “The EncapsulatedBits dictionary represents encapsulated key bits comprised of a sharedKey and a ciphertext.” There is no dedicated Security/Privacy Considerations section in the draft, so beyond that definition sentence there is no field-level security/privacy fact to cite. |
The draft also extends JsonWebKey with pub and priv fields (WICG §5, per RFC 9964) for the algorithms’ JWK representations.
| Member | Contract |
|---|---|
encapsulateKey(alg, key, sharedAlg, extractable, usages) | Runs the KEM encapsulation against the recipient public key and resolves to an EncapsulatedKey: the freshly encapsulated shared secret as a CryptoKey (algorithm sharedAlg, with the requested usages) plus the ciphertext to send |
encapsulateBits(alg, key) | Same encapsulation, but the shared secret comes back as raw ArrayBuffer bits (an EncapsulatedBits) instead of an imported CryptoKey |
decapsulateKey(alg, key, ciphertext, sharedAlg, extractable, usages) | Reverses encapsulation with the private key: resolves to the shared secret as a CryptoKey |
decapsulateBits(alg, key, ciphertext) | Decapsulates to raw ArrayBuffer bits |
getPublicKey(key, keyUsages) | Derives the public CryptoKey from an asymmetric private key, so only the private half needs to be stored |
static supports(operation, algorithm, length?) / static supports(operation, algorithm, additionalAlgorithm) | Static capability check: is this algorithm identifier (with parameters, key length, or a second algorithm) supported for the named operation on this build? |
Errors
The six methods (encapsulateKey, encapsulateBits, decapsulateKey, decapsulateBits, getPublicKey, and exportKey) fail in two different ways, and they are not interchangeable: a named DOMException that an implementer can catch by name, versus a promise rejection produced by algorithm normalization whose value is the normalization result itself and carries no name to catch. Every throw and rejection below is a step of the WICG — WebCrypto Modern Algorithms draft (the partial SubtleCrypto interface, §3.2); the W3C Web Cryptography API base Recommendation contributes none of these sites — they are all new draft algorithm steps.
Named DOMException sites — catchable by name
Twelve named throw sites across the five asynchronous methods. Each sentence is quoted verbatim from the draft.
| Method | Error | Trigger clause (verbatim, WICG draft) |
|---|---|---|
encapsulateKey() | InvalidAccessError | “If the name member of normalizedEncapsulationAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of encapsulationKey then throw an InvalidAccessError.” |
encapsulateKey() | InvalidAccessError | “If the [[usages]] internal slot of encapsulationKey does not contain an entry that is "encapsulateKey", then throw an InvalidAccessError.” |
encapsulateBits() | InvalidAccessError | “If the name member of normalizedEncapsulationAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of encapsulationKey then throw an InvalidAccessError.” |
encapsulateBits() | InvalidAccessError | “If the [[usages]] internal slot of encapsulationKey does not contain an entry that is "encapsulateBits", then throw an InvalidAccessError.” |
decapsulateKey() | InvalidAccessError | “If the name member of normalizedDecapsulationAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of decapsulationKey then throw an InvalidAccessError.” |
decapsulateKey() | InvalidAccessError | “If the [[usages]] internal slot of decapsulationKey does not contain an entry that is "decapsulateKey", then throw an InvalidAccessError.” |
decapsulateBits() | InvalidAccessError | “If the name member of normalizedDecapsulationAlgorithm is not equal to the name attribute of the [[algorithm]] internal slot of decapsulationKey then throw an InvalidAccessError.” |
decapsulateBits() | InvalidAccessError | “If the [[usages]] internal slot of decapsulationKey does not contain an entry that is "decapsulateBits", then throw an InvalidAccessError.” |
getPublicKey() | InvalidAccessError | “If the [[type]] internal slot of key is not "private", then throw an InvalidAccessError.” |
getPublicKey() | NotSupportedError | “If the cryptographic algorithm identified by algorithm does not support deriving a public key from a private key, then return a Promise rejected with a NotSupportedError.” |
getPublicKey() | SyntaxError | “If usages contains an entry which is not supported for a public key by the algorithm identified by algorithm, then throw a SyntaxError.” |
getPublicKey() | OperationError | “If an error occurred, then throw a OperationError.” (verbatim, including the article “a”) |
Promise rejections from normalization — not catchable by name
Six sites return a promise rejected with the normalization result, not with a named DOMException. An implementer cannot catch these by name because the rejection value is the failed normalization result itself.
| Method | Trigger clause (verbatim, WICG draft) |
|---|---|
encapsulateKey() | “If an error occurred, return a Promise rejected with normalizedEncapsulationAlgorithm.” |
encapsulateKey() | “If an error occurred, return a Promise rejected with normalizedSharedKeyAlgorithm.” |
encapsulateBits() | “If an error occurred, return a Promise rejected with normalizedEncapsulationAlgorithm.” |
decapsulateKey() | “If an error occurred, return a Promise rejected with normalizedDecapsulationAlgorithm.” |
decapsulateKey() | “If an error occurred, return a Promise rejected with normalizedSharedKeyAlgorithm.” |
decapsulateBits() | “If an error occurred, return a Promise rejected with normalizedDecapsulationAlgorithm.” |
Because these rejections are returned (not thrown), the draft's throw-to-rejection convention does not apply to them — see the Lifecycle section.
supports() — no throw contract, and the one implied WebIDL TypeError
The static supports() method never throws: every failure path returns false. This is stated by the draft's own algorithm, not an inference:
| Clause (verbatim, WICG draft) |
|---|
| “If operation is not one of "encrypt", "decrypt", "sign", "verify", "digest", "generateKey", "deriveKey", "deriveBits", "importKey", "exportKey", "wrapKey", "unwrapKey", "encapsulateKey", "encapsulateBits", "decapsulateKey", "decapsulateBits" or "getPublicKey", return false.” |
| “If an error occurred, return false.” |
Separate from that algorithm contract is a WebIDL binding-level TypeError implied by the IDL — not an algorithm step. The first overload declares optional [EnforceRange] unsigned long? length = null, so a length that is a non-integer or outside [0, 232−1] produces a WebIDL TypeError before the algorithm body runs. The draft's algorithm does not raise this — the [EnforceRange] extended attribute in the IDL does.
Lifecycle
For each of the six methods the contract records one of exactly two cases: the draft states the promise/parallel-task pattern (quoted below), or the draft does not state it (recorded as an absence, not composed and not “not-applicable”). The draft states the pattern identically in §3.2.1–§3.2.5; the four sentences are:
“Let realm be the relevant realm of this.”
“Let promise be a new Promise.”
“Return promise and perform the remaining steps in parallel.”
“Queue a global task on the crypto task source, given realm’s global object, to perform the remaining steps.”
And the draft converts any throw inside the parallel work into a promise rejection with this convention, stated verbatim in each of the same five methods:
“If the following steps or referenced procedures say to throw an error, queue a global task on the crypto task source, given realm’s global object, to reject promise with the returned error; and then terminate the algorithm.”
Per method, confirmed against the draft’s own text (presence of the five sentences checked in each §3.2.x body):
| Method | Promise/parallel-task pattern |
|---|---|
encapsulateKey() | The draft states it — all four sentences above, plus the rejection convention. |
encapsulateBits() | The draft states it — all four sentences above, plus the rejection convention. |
decapsulateKey() | The draft states it — all four sentences above, plus the rejection convention. |
decapsulateBits() | The draft states it — all four sentences above, plus the rejection convention. |
getPublicKey() | The draft states it — all four sentences above, plus the rejection convention. One difference the source itself makes: its NotSupportedError (“then return a Promise rejected with a NotSupportedError”) is returned before “Let realm be the relevant realm of this.”, so that rejection does not go through the queue-a-global-task convention. |
supports() | The draft does not state the pattern. supports() is synchronous and “returns a boolean”, with no “Let promise be a new Promise” step, no parallel section, and no queue-a-global-task step. This is a difference the source itself makes (the method has no promise at all), not one drawn here. |
What the draft does not state: it has no dedicated lifecycle prose beyond the sentences above, and it assigns the two dictionary fields (sharedKey, ciphertext) no lifecycle of their own — they are populated by the encapsulate/decapsulate algorithms and have no independent “created when” step beyond being fields of the dictionaries named in §4. The draft also does not state any timing or ordering guarantee for the “Queue a global task … perform the remaining steps” step relative to the encapsulate/decapsulate operation other than what the quoted sentences say.
The new algorithm roster
Twelve algorithm families are registered — 37 registered names in total — each with its own operations section in the spec (key generation, import/export, and the operations below). All are optional to implement per the spec — use SubtleCrypto.supports() to detect them. The Reference column cites both the crypto-math standard and the WICG registration section that carries the web-facing grammar (registered name strings, WebIDL parameter dictionaries, JWK mappings).
| Registered name(s) | Kind | Primary operations | Reference (crypto math · WICG web grammar) |
|---|---|---|---|
| ML-KEM-512, ML-KEM-768, ML-KEM-1024 | Post-quantum key encapsulation | encapsulateKey/Bits, decapsulateKey/Bits, generateKey, importKey, exportKey | FIPS 203 · WICG §6.2 |
| MLKEM768-P256, MLKEM768-X25519, MLKEM1024-P384 | Hybrid post-quantum + classical key encapsulation | encapsulateKey/Bits, decapsulateKey/Bits, generateKey, importKey, exportKey | draft-irtf-cfrg-concrete-hybrid-kems · WICG §7.2 |
| ML-DSA-44, ML-DSA-65, ML-DSA-87 | Post-quantum signatures | sign, verify, generateKey, importKey, exportKey | FIPS 204 · WICG §8.2 |
| SLH-DSA-SHA2-128s, SLH-DSA-SHA2-128f, SLH-DSA-SHA2-192s, SLH-DSA-SHA2-192f, SLH-DSA-SHA2-256s, SLH-DSA-SHA2-256f, SLH-DSA-SHAKE-128s, SLH-DSA-SHAKE-128f, SLH-DSA-SHAKE-192s, SLH-DSA-SHAKE-192f, SLH-DSA-SHAKE-256s, SLH-DSA-SHAKE-256f | Post-quantum hash-based signatures | sign, verify, generateKey, importKey, exportKey | FIPS 205 · WICG §9.2 |
| AES-OCB | Authenticated encryption (key length via params) | encrypt, decrypt, generateKey, importKey, exportKey, getKeyLength | RFC 7253 · WICG §10.2 |
| ChaCha20-Poly1305 | Authenticated encryption | encrypt, decrypt, generateKey, importKey, exportKey, getKeyLength | RFC 8439 · WICG §11.2 |
| SHA3-256, SHA3-384, SHA3-512 | SHA-3 digests | digest | FIPS 202 · WICG §12.2 |
| cSHAKE128, cSHAKE256 | Customizable XOF | digest | NIST SP 800-185 · WICG §13.2 |
| TurboSHAKE128, TurboSHAKE256 | Fast XOF | digest | RFC 9861 · WICG §14.2 |
| KT128, KT256 (KangarooTwelve) | Fast XOF / hashing | digest | RFC 9861 · WICG §15.2 |
| KMAC128, KMAC256 | Keyed MAC (Keccak) | sign, verify, generateKey, importKey, exportKey, getKeyLength | NIST SP 800-185 · WICG §16.2 |
| Argon2d, Argon2i, Argon2id | Password-based key derivation | deriveBits, importKey, getKeyLength | RFC 9106 · WICG §17.2 |
Examples
// 1. Feature-detect first — the method and every algorithm are optional
const kemOK = SubtleCrypto.supports?.("encapsulateKey", "ML-KEM-768") ?? false;
if (!kemOK) throw new DOMException("ML-KEM-768 is unavailable", "NotSupportedError");
// 2. Recipient generates an ML-KEM key pair
const pair = await crypto.subtle.generateKey("ML-KEM-768", true, [
"encapsulateKey", "decapsulateKey",
]);
// 3. Sender encapsulates a shared secret against the recipient public key
const { sharedKey, ciphertext } = await crypto.subtle.encapsulateKey(
"ML-KEM-768", pair.publicKey, "AES-GCM", true, ["encrypt", "decrypt"],
);
// -> send { ciphertext } to the recipient; keep sharedKey local
// 4. Recipient decapsulates with the private key — same shared secret
const recovered = await crypto.subtle.decapsulateKey(
"ML-KEM-768", pair.privateKey, ciphertext, "AES-GCM", true, ["encrypt", "decrypt"],
);
Source: composed from the WICG partial SubtleCrypto interface and ML-KEM registered names and operations; the draft does not provide an ML-KEM JavaScript example.
The three remaining methods — encapsulateBits, decapsulateBits, and getPublicKey — are not exercised by the snippet above. The short composed example below covers them. Like the example above, it is composed from the named sources, not copied from the draft, and the draft does not provide a JavaScript example for these members. It reuses pair (the ML-KEM key pair generated above) and uses only identifiers the draft or the example above already declare.
// encapsulateBits — the raw-bits form: no CryptoKey import of the shared secret
// sourceRef: https://wicg.github.io/webcrypto-modern-algos/#SubtleCrypto-method-encapsulateBits
const bits = await crypto.subtle.encapsulateBits("ML-KEM-768", pair.publicKey);
// bits.sharedKey → ArrayBuffer; bits.ciphertext → ArrayBuffer (send this)
// sourceRef: https://wicg.github.io/webcrypto-modern-algos/#x4-encapsulation-dictionaries
// decapsulateBits — recover the same raw bits on the recipient side
// sourceRef: https://wicg.github.io/webcrypto-modern-algos/#SubtleCrypto-method-decapsulateBits
const bitsRecovered = await crypto.subtle.decapsulateBits(
"ML-KEM-768", pair.privateKey, bits.ciphertext,
);
// bitsRecovered → ArrayBuffer, equal to bits.sharedKey
// getPublicKey — recover the public half from a stored private key
// sourceRef: https://wicg.github.io/webcrypto-modern-algos/#SubtleCrypto-method-getPublicKey
const recoveredPublic = await crypto.subtle.getPublicKey(
pair.privateKey, ["encapsulateKey"],
);
Source: composed from the WICG encapsulateBits method, decapsulateBits method, getPublicKey method, and Encapsulation dictionaries; the draft does not provide an ML-KEM JavaScript example for these three members. The usage value "encapsulateKey" in the getPublicKey call is the KeyUsage enum member declared in the same partial interface (the draft’s getPublicKey prose does not itself enumerate which usages each algorithm supports for a public key).
Browser compatibility
Cross-browser support is recorded in browser-compat-data (BCD) as of 2026-10-06; the earlier interim view built from ChromeStatus ship data is superseded (BCD carried no entries for these members as of 2026-07-24). BCD flags all six members experimental.
| Browser | encapsulateKey/Bits · decapsulateKey/Bits | getPublicKey | static supports() | Notes |
|---|---|---|---|---|
| Chrome | 155 | 155 | 155 | BCD version_added: 155, status experimental; trunk runtime flag WebCryptoPQC reads “stable” |
| Edge | mirrors Chrome | mirrors Chrome | mirrors Chrome | BCD “mirror” — follows the Chromium release |
| Chrome Android / WebView | mirrors Chrome | mirrors Chrome | mirrors Chrome | BCD “mirror” |
| Firefox | preview | no support | no support | The four encapsulate/decapsulate methods are in preview builds only (BCD “preview”) |
| Safari | no support | no support | no support | BCD version_added: false |
ChromeStatus (updated 2026-09-11) still records the feature as “Proposed” with no desktop ship milestone — it lags the shipped state BCD records; this page reports both rather than choosing.
Source: BCDapi/SubtleCrypto.json (fetched 2026-10-06; encapsulateKey, encapsulateBits, decapsulateKey, decapsulateBits, getPublicKey, supports_static); chromestatus.com/feature/5198951632470016; Chromium runtime_enabled_features.json5
Specifications
| Specification | Status |
|---|---|
| WebCrypto Modern Algorithms | WICG draft (incubation) |
| Web Cryptography API | W3C Recommendation — the base SubtleCrypto interface this draft extends |
| FIPS 203 / 204 / 205, FIPS 202, NIST SP 800-185, RFC 7253 / 8439 / 9106 / 9861, draft-irtf-cfrg-concrete-hybrid-kems | Normative algorithm references (linked from the draft) |