Skip to content

Improve algorithm steps for Modern Algorithms' supports() method - #558

Merged
twiss merged 7 commits into
w3c:mainfrom
panva:supports-improvements
Aug 11, 2026
Merged

Improve algorithm steps for Modern Algorithms' supports() method#558
twiss merged 7 commits into
w3c:mainfrom
panva:supports-improvements

Conversation

@panva

@panva panva commented Aug 7, 2026

Copy link
Copy Markdown
Member

The Modern Algorithms specification defines SubtleCrypto.supports() by normalizing an algorithm and executing its operation steps until it encounters unavailable key or data, key generation, a return, or an exception.

This makes the ordering and explicitness of validation in the core Web Cryptography specification observable. Some core operations currently reach one of those stopping points before checking parameters that supports() does have. This can make supports() return true for an interaction that:

  • cannot succeed with any key or input;
  • is not defined for the selected algorithms;
  • is not expected to be supported by underlying cryptographic libraries; or
  • is already deliberately rejected by implementations.

This PR makes those outcomes observable before supports() reaches its stopping point.

Changes

  • Move existing AES-GCM IV, additional-data, and tag-length validation ahead of plaintext or ciphertext access.
  • Check HKDF's 255-block output limit before accessing key material.
  • Reject an explicitly zero-length HMAC import before examining key data.
  • Check necessary RSA modulus-length and public-exponent constraints before key generation.
  • Validate supplied X25519 and ECDH public keys and maximum derivation lengths before accessing the unavailable private key.
  • Derive the ECDH output limit from the curve's EC domain parameters, including curves defined by applicable specifications.
  • Define NamedCurve as an enum so names not defined by the core or an applicable specification fail during normalization.
  • Make the fixed-output-hash boundary explicit for RSA, ECDSA, HMAC, HKDF, and PBKDF2.

The XOF checks establish an intentionally unsupported boundary rather than claiming every such composition is cryptographically impossible/undefined. Selecting an output length for an XOF does not turn it into the fixed-output hash expected by these traditional algorithms. In particular, implementations already reject RSA and ECDSA combinations with XOF digests using NotSupportedError. This just sets it as baseline.

Successful operations are unchanged.

Examples

Each of the following now returns false.

AES-GCM parameters

SubtleCrypto.supports("encrypt", {
  name: "AES-GCM",
  iv: new Uint8Array(12),
  tagLength: 31,
})

A 31-bit AES-GCM tag is never valid, regardless of key or plaintext.

HKDF output length

SubtleCrypto.supports("deriveBits", {
  name: "HKDF",
  hash: "SHA-256",
  salt: new Uint8Array(),
  info: new Uint8Array(),
}, 65288)

With SHA-256 the maximum is 65280 bits, so 65288 bits can never be derived.

XOFs in traditional algorithms

SubtleCrypto.supports("generateKey", {
  name: "HMAC",
  hash: { name: "cSHAKE128", outputLength: 256 },
})

Modern Algorithms implementations deliberately exclude XOF digests from these traditional algorithms. Selecting an output length does not turn cSHAKE into a fixed-output hash.

Undefined named curves

SubtleCrypto.supports("importKey", {
  name: "ECDSA",
  namedCurve: "not-a-curve",
})

No import using an undefined curve could ever succeed.

Zero-length HMAC imports

SubtleCrypto.supports("importKey", {
  name: "HMAC",
  hash: "SHA-256",
  length: 0,
})

No HMAC key data can satisfy an explicitly requested length of zero.

RSA key generation parameters

SubtleCrypto.supports("generateKey", {
  name: "RSA-PSS",
  modulusLength: 2048,
  publicExponent: new Uint8Array([2]),
  hash: "SHA-256",
})

No RSA key can use an even public exponent.

X25519 derivation length

SubtleCrypto.supports("deriveBits", {
  name: "X25519",
  public: publicKey,
}, 257)

X25519 produces at most 256 bits, so 257 bits can never be derived. Refs: WICG/webcrypto-modern-algos#74

ECDH derivation length

SubtleCrypto.supports("deriveBits", {
  name: "ECDH",
  public: publicKey,
}, 257)

With a P-256 public key, the field element encodes to 256 bits. The output limit is derived from the public key’s EC domain parameters, so extended named curves are handled without enumeration. Refs: WICG/webcrypto-modern-algos#74


Preview | Diff

Move parameter-only checks ahead of plaintext and ciphertext checks so
support queries can observe them.

For example, this now returns false:

    SubtleCrypto.supports("encrypt", {
      name: "AES-GCM",
      iv: new Uint8Array(12),
      tagLength: 31,
    })

A 31-bit AES-GCM tag is never valid, regardless of key or plaintext.
Comment thread spec/Overview.html Outdated
Comment thread spec/Overview.html Outdated
@panva

panva commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

@twiss to confirm then

The rest is fine from your POV?

@twiss

twiss commented Aug 7, 2026

Copy link
Copy Markdown
Member

Yeah, I'll do one more pass afterwards but I think the rest looks good 👍 Thanks!

@panva
panva force-pushed the supports-improvements branch from 1583eb8 to c635495 Compare August 7, 2026 15:25
@panva

panva commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

@twiss done , i'll leave the one review thread unresolved until the PR for modern algorithms is there.

@twiss twiss left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Final nit below.

Comment thread spec/Overview.html
panva added 6 commits August 11, 2026 15:11
Check HKDF's 255-block output limit before the operation reaches
unavailable key material.

For example, this now returns false:

    SubtleCrypto.supports("deriveBits", {
      name: "HKDF",
      hash: "SHA-256",
      salt: new Uint8Array(),
      info: new Uint8Array(),
    }, 65288)

With SHA-256 the maximum is 65280 bits, so 65288 bits can never be
derived.
Expose the unconditional zero-length failure before import reaches unavailable key data.

For example, this now returns false:

    SubtleCrypto.supports("importKey", {
      name: "HMAC",
      hash: "SHA-256",
      length: 0,
    })

No HMAC key data can satisfy an explicitly requested length of zero.
Expose universally invalid modulus lengths and public exponents before
the operation reaches key generation.

For example, this now returns false:

    SubtleCrypto.supports("generateKey", {
      name: "RSA-PSS",
      modulusLength: 2048,
      publicExponent: new Uint8Array([2]),
      hash: "SHA-256",
    })

No RSA key can use an even public exponent.
Expose impossible public-key inputs and overlong derivations before the
operation reaches unavailable base key material.

For example, this now returns false:

    SubtleCrypto.supports("deriveBits", {
      name: "X25519",
      public: publicKey,
    }, 257)

X25519 produces at most 256 bits, so 257 bits can never be derived.
Expose impossible public-key inputs and overlong derivations before the
operation reaches unavailable base key material.

For example, with a P-256 public key, this now returns false:

    SubtleCrypto.supports("deriveBits", {
      name: "ECDH",
      public: publicKey,
    }, 257)

A P-256 field element encodes to 256 bits. The output limit is derived
from the public key's EC domain parameters, so extended named curves are
handled without enumeration.
Expose unsupported ECDSA and ECDH named curves before import reaches unavailable key data.

For example, this now returns false:

    SubtleCrypto.supports("importKey", {
      name: "ECDSA",
      namedCurve: "not-a-curve",
    })

NamedCurve remains a DOMString so applicable specifications can define additional curves.
@panva
panva force-pushed the supports-improvements branch from c635495 to b16487f Compare August 11, 2026 13:12
@twiss
twiss merged commit 811c24c into w3c:main Aug 11, 2026
2 checks passed
github-actions Bot added a commit that referenced this pull request Aug 11, 2026
SHA: 811c24c
Reason: push, by twiss

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@panva
panva deleted the supports-improvements branch August 11, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants