Skip to content

Add ML-DSA (FIPS 204) post-quantum signature support#3479

Open
iNinja wants to merge 11 commits into
dev8xfrom
iinglese/ml-dsa-8x-v2
Open

Add ML-DSA (FIPS 204) post-quantum signature support#3479
iNinja wants to merge 11 commits into
dev8xfrom
iinglese/ml-dsa-8x-v2

Conversation

@iNinja
Copy link
Copy Markdown
Contributor

@iNinja iNinja commented May 8, 2026

Add ML-DSA (FIPS 204) post-quantum signature support

This PR adds ML-DSA (Module-Lattice-Based Digital Signature Algorithm, FIPS 204) support to Microsoft.IdentityModel.Tokens, enabling post-quantum digital signatures across the JOSE pipeline — JWS signing/verification, JWK key representation, X.509 certificate key extraction, and JWK conversion.

Standards

Standard Status Usage
FIPS 204 Final ML-DSA algorithm (key gen, sign, verify)
RFC 9881 Final (Oct 2025) X.509 algorithm OIDs for ML-DSA-44/65/87
draft-ietf-cose-dilithium-11 (RFC 9964 pending) AUTH48 — content frozen JWK key type (kty=AKP), parameter names (pub, priv), JWS algorithm identifiers, thumbprint computation

What's included

New types

  • MlDsaSecurityKeyAsymmetricSecurityKey subclass wrapping MLDsa; supports key size, private key detection, JWK thumbprint computation
  • MlDsaAdapter (internal) — creates MLDsa from JWK parameters with pub/priv consistency validation

Modified types

  • AsymmetricAdapter — ML-DSA sign/verify delegates (byte[], offset, span), X.509 ML-DSA routing
  • AsymmetricSignatureProvider — ML-DSA key size maps, hash algorithm guard pattern (TryGetHashAlgorithmName)
  • SupportedAlgorithms — ML-DSA algorithm collection, algorithm/key parameter set enforcement
  • JsonWebKeyPub/Priv properties, AKP key size, HasPrivateKey, thumbprint computation
  • JsonWebKeySerializer — read/write pub/priv parameters
  • JsonWebKeyConverterConvertFromMlDsaSecurityKey, TryConvertToMlDsaSecurityKey, X.509→JWK conversion for ML-DSA certificates (x5c and extractKeyMaterial modes)
  • X509SecurityKey — ML-DSA OID detection (RFC 9881), MlDsaPublicKey/MlDsaPrivateKey properties with .NET 6 platform compatibility handling
  • CryptoTelemetry — ML-DSA key algorithm identifiers
  • SecurityAlgorithmsMlDsa44, MlDsa65, MlDsa87 constants
  • JsonWebAlgorithmsKeyTypesAkp constant
  • JsonWebKeyParameterNamesPub, Priv constants with UTF8 equivalents

Dependencies

  • Microsoft.Bcl.Cryptography ≥ 10.0.2 — provides MLDsa type on all Wilson TFMs
  • System.Memory upgraded 4.5.5 → 4.6.3 (transitive requirement)

Design decisions

  • No conditional compilationMLDsa is available on all TFMs via the BCL compatibility package
  • No [Experimental] on Wilson types — only internal call sites that invoke .NET experimental X.509 extension methods use #pragma SYSLIB5006 suppression
  • Algorithm/key enforcementIsSupportedAlgorithm validates that the ML-DSA key's parameter set matches the requested JOSE algorithm (prevents algorithm confusion)
  • Pub/priv consistency validation — JWK import verifies the claimed pub matches the key derived from priv seed
  • kty=AKP with mandatory alg — per draft-ietf-cose-dilithium; routing checks both kty and alg, never kty alone
  • JWK thumbprint — canonical form {"alg","kty","pub"} in lexicographic order
  • Private key format — 32-byte seed only (not expanded key), zeroed after use in finally blocks
  • X.509 key extractionMlDsaPrivateKey catches PlatformNotSupportedException on .NET 6 where private key extraction is not supported

Test coverage (93 tests)

Category Tests
Key construction & properties 5
JWK thumbprint (deterministic, pub/priv match, cross-key, X509 consistency) 7
JWK round-trip (SecurityKey ↔ JWK ↔ JSON) 6
X.509 key size, thumbprint, JWK conversion 15
JWK negative tests (missing alg, missing pub, invalid alg, pub/priv mismatch) 4
Algorithm/key mismatch enforcement (MlDsaSecurityKey, JsonWebKey, X509SecurityKey) 15
Public-key-only signing/verification 2
Signature correctness (sign/verify round-trip, tampering, cross-key) 7
E2E JWT create/validate (JsonWebTokenHandler, JwtSecurityTokenHandler, experimental ValidationParameters, JWK keys) 12
E2E JWT with X.509 (sign with X509SecurityKey, cross-key-type validation) 6
Existing asymmetric signature tests 523 (unchanged, no regressions)

Tests run on: net462, net472, net6.0, net8.0, net9.0, net10.0

Known limitations

  1. X.509 ML-DSA private key on .NET 6GetMLDsaPrivateKey() throws PlatformNotSupportedException. Verification works; signing requires MlDsaSecurityKey with a standalone key.
  2. X.509 certificate creationCertificateRequest(string, MLDsa) is only available on .NET 10. Test certificates are pre-generated PFX embedded as base64 constants.
  3. JOSE draft status — draft-ietf-cose-dilithium is in AUTH48 (RFC 9964 pending). Content is frozen; algorithm identifiers and wire formats are final.
  4. BCL package net6.0 warnings — suppressed via targeted Directory.Build.targets overrides. Remove when net6.0 is dropped from SrcTargets.

Implement ML-DSA-44, ML-DSA-65, and ML-DSA-87 digital signature support
in Microsoft.IdentityModel.Tokens, enabling post-quantum signatures
across the JOSE pipeline: JWS signing/verification, JWK representation,
X.509 certificate key extraction, and JWK conversion.

Standards: FIPS 204 (Final), RFC 9881 (Final),
draft-ietf-cose-dilithium v11 (RFC 9964 pending)

Targeting dev8x (Wilson 8.x) with representAsRsaKey parameter naming.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@iNinja iNinja requested a review from a team as a code owner May 8, 2026 13:22
@iNinja iNinja requested a review from Copilot May 8, 2026 13:23
Comment thread build/dependencies.props
<NewtonsoftVersion>13.0.3</NewtonsoftVersion>
<SystemDiagnosticSourceVersion>6.0.2</SystemDiagnosticSourceVersion>
<SystemMemoryVersion>4.5.5</SystemMemoryVersion>
<SystemMemoryVersion>4.6.3</SystemMemoryVersion>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is being bumped as a requirement from Microsoft.Bcl.Cryptography.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I guess this drives the requirement upwards for entire dependency tree?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes. Microsoft.Bcl.Cryptography 10.0.2 is a new dependency that provides the MLDsa API on downlevel TFMs (net462, net472, net6.0, net8.0, net9.0). Without it we can only support ML-DSA on .NET 10+. System.Memory 4.5.5 → 4.6.3 is a transitive requirement from Microsoft.Bcl.Cryptography. Both will flow to consumers of the NuGet packages.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces ML-DSA (FIPS 204) post-quantum signature support across the IdentityModel JOSE pipeline, including new key types, JWK serialization/conversion, X.509 extraction, algorithm support/enforcement, telemetry, and extensive test coverage.

Changes:

  • Added MlDsaSecurityKey and MlDsaAdapter, plus ML-DSA signing/verification support in AsymmetricAdapter / AsymmetricSignatureProvider.
  • Extended JWK and X.509 handling for ML-DSA (kty=AKP, pub/priv, thumbprints, X509→JWK conversion).
  • Added test utilities and new test suites gated by platform support, plus dependency updates to enable MLDsa across TFMs.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/Microsoft.IdentityModel.Tokens.Tests/MlDsaSecurityKeyTests.cs Adds focused unit + E2E JWT coverage for ML-DSA keys, JWK, thumbprints, and X.509 scenarios.
test/Microsoft.IdentityModel.Tokens.Tests/AsymmetricSignatureTests.cs Extends existing signing/verifying theory data to include ML-DSA keys/algorithms when supported.
test/Microsoft.IdentityModel.Tokens.Tests/AsymmetricSignatureTestData.cs Adds ML-DSA key sets and algorithm-variation wiring for signature theory data.
test/Microsoft.IdentityModel.TestUtils/MlDsaKeyingMaterial.cs Introduces lazily-initialized ML-DSA test keys and embedded X.509 PFX material.
test/Microsoft.IdentityModel.TestUtils/MlDsaConditionalAttributes.cs Adds conditional xUnit attributes to skip ML-DSA tests on unsupported platforms.
src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs Adds ML-DSA OID detection, cached public/private extraction, key size/thumbprint support.
src/Microsoft.IdentityModel.Tokens/Telemetry/CryptoTelemetry.cs Adds ML-DSA key algorithm identifiers for telemetry reporting.
src/Microsoft.IdentityModel.Tokens/SupportedAlgorithms.cs Adds ML-DSA signing algorithms and hash-selection guard (TryGetHashAlgorithmName).
src/Microsoft.IdentityModel.Tokens/SecurityAlgorithms.cs Adds ML-DSA JOSE algorithm string constants.
src/Microsoft.IdentityModel.Tokens/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt Public API additions for ML-DSA key type and JWK parameters.
src/Microsoft.IdentityModel.Tokens/PublicAPI/net6.0/PublicAPI.Unshipped.txt Public API additions for ML-DSA key type and JWK parameters.
src/Microsoft.IdentityModel.Tokens/PublicAPI/net8.0/PublicAPI.Unshipped.txt Public API additions for ML-DSA key type and JWK parameters.
src/Microsoft.IdentityModel.Tokens/PublicAPI/net9.0/PublicAPI.Unshipped.txt Public API additions for ML-DSA key type and JWK parameters.
src/Microsoft.IdentityModel.Tokens/PublicAPI/net10.0/PublicAPI.Unshipped.txt Public API additions for ML-DSA key type and JWK parameters.
src/Microsoft.IdentityModel.Tokens/PublicAPI/net462/PublicAPI.Unshipped.txt Public API additions for ML-DSA key type and JWK parameters.
src/Microsoft.IdentityModel.Tokens/PublicAPI/net472/PublicAPI.Unshipped.txt Public API additions for ML-DSA key type and JWK parameters.
src/Microsoft.IdentityModel.Tokens/MlDsaSecurityKey.cs Adds new SecurityKey wrapper for MLDsa with key-size/private-key detection and thumbprints.
src/Microsoft.IdentityModel.Tokens/MlDsaAdapter.cs Adds JWK→MLDsa import and pub/priv consistency validation.
src/Microsoft.IdentityModel.Tokens/Microsoft.IdentityModel.Tokens.csproj Adds Microsoft.Bcl.Cryptography package reference to provide MLDsa across TFMs.
src/Microsoft.IdentityModel.Tokens/LogMessages.cs Adds ML-DSA specific error messages for JWK import and X.509 extraction failure modes.
src/Microsoft.IdentityModel.Tokens/JsonWebKeyParameterNames.cs Adds pub/priv constants and UTF-8 byte spans for high-performance JSON parsing/writing.
src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs Adds ML-DSA key conversion paths: SecurityKey↔JWK and X.509→JWK routing for AKP.
src/Microsoft.IdentityModel.Tokens/JsonWebKey.cs Adds Pub/Priv properties, AKP key sizing, private-key detection, and thumbprint support.
src/Microsoft.IdentityModel.Tokens/JsonWebAlgorithmsKeyTypes.cs Adds AKP key type constant for the JOSE draft key type.
src/Microsoft.IdentityModel.Tokens/Json/JsonWebKeySerializer.cs Adds read/write support for pub/priv parameters.
src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt Tracks new internal APIs added for ML-DSA support.
src/Microsoft.IdentityModel.Tokens/GlobalSuppressions.cs Adds CA1031 suppressions for ML-DSA try-pattern conversion and platform probing.
src/Microsoft.IdentityModel.Tokens/AsymmetricSignatureProvider.cs Adds ML-DSA key size minima and bypasses hash selection for “pure signing” algorithms.
src/Microsoft.IdentityModel.Tokens/AsymmetricAdapter.cs Adds ML-DSA sign/verify delegates, X.509 ML-DSA routing, and span-based signing when available.
Directory.Build.targets Adds targeted target overrides to suppress net6.0 compatibility warnings from new crypto dependencies.
build/dependencies.props Introduces Microsoft.Bcl.Cryptography version and updates System.Memory version.

Comment thread src/Microsoft.IdentityModel.Tokens/AsymmetricAdapter.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/AsymmetricAdapter.cs
Comment thread src/Microsoft.IdentityModel.Tokens/Telemetry/CryptoTelemetry.cs
Comment thread test/Microsoft.IdentityModel.TestUtils/MlDsaKeyingMaterial.cs
- Refactor InitializeUsingX509SecurityKey into explicit routing:
  InitializeUsingX509MlDsa, InitializeUsingX509Rsa, with clear
  unsupported key type fallback (IDX10725). Extensible pattern for
  future PQC algorithms (Composite ML-DSA, SLH-DSA).
- Fix X509 ML-DSA telemetry: extract GetX509KeyAlgorithmId helper
  to correctly identify ML-DSA certs instead of reporting UNKNOWN.
- Use EphemeralKeySet for PFX loading on .NET 6+ to avoid persisting
  keys to disk; fall back to Exportable on .NET Framework.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 3 comments.

Comment thread src/Microsoft.IdentityModel.Tokens/AsymmetricAdapter.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/MlDsaSecurityKey.cs
Comment thread test/Microsoft.IdentityModel.Tokens.Tests/MlDsaSecurityKeyTests.cs
…fix Task style

- Add ECDsa routing in InitializeUsingX509SecurityKey so ECDSA X509
  certificates are handled correctly instead of falling through to
  the unsupported key type error
- Broaden exception handling in MlDsaSecurityKey.PrivateKeyStatus and
  HasPrivateKey to return Unknown/false for non-CryptographicException
  failures (e.g., platform limitations), matching the documented contract
- Use consistent short-form Task in test method signatures
- Add CA1031 suppression for MlDsaSecurityKey.HasPrivateKey

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Comment thread src/Microsoft.IdentityModel.Tokens/MlDsaSecurityKey.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/JsonWebKey.cs Outdated
…ey check

- Don't cache _hasPrivateKey on general Exception in HasPrivateKey so
  PrivateKeyStatus can independently return Unknown for indeterminate cases
- Use !string.IsNullOrEmpty(Priv) for AKP HasPrivateKey in JsonWebKey,
  consistent with MlDsaAdapter which treats empty priv as missing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Comment thread src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs
Comment thread src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs
When AKP x5c validation rejects a certificate (non-ML-DSA cert or
alg mismatch), clear webKey.ConvertedSecurityKey to prevent subsequent
TryConvertToSecurityKey calls from returning the cached key and
bypassing validation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Comment thread test/Microsoft.IdentityModel.Tokens.Tests/MlDsaSecurityKeyTests.cs
Comment thread test/Microsoft.IdentityModel.Tokens.Tests/MlDsaSecurityKeyTests.cs Outdated
Add using declarations to public-only X509Certificate2 instances
created from RawData to avoid leaking certificate handles.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/Microsoft.IdentityModel.Tokens/JsonWebKey.cs
Comment thread src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs
Comment thread src/Microsoft.IdentityModel.Tokens/JsonWebKeyConverter.cs
Comment thread build/dependencies.props
<NewtonsoftVersion>13.0.3</NewtonsoftVersion>
<SystemDiagnosticSourceVersion>6.0.2</SystemDiagnosticSourceVersion>
<SystemMemoryVersion>4.5.5</SystemMemoryVersion>
<SystemMemoryVersion>4.6.3</SystemMemoryVersion>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I guess this drives the requirement upwards for entire dependency tree?

iNinja and others added 4 commits May 18, 2026 18:22
# Conflicts:
#	src/Microsoft.IdentityModel.Tokens/InternalAPI.Unshipped.txt
#	src/Microsoft.IdentityModel.Tokens/PublicAPI/net10.0/PublicAPI.Unshipped.txt
#	src/Microsoft.IdentityModel.Tokens/PublicAPI/net462/PublicAPI.Unshipped.txt
#	src/Microsoft.IdentityModel.Tokens/PublicAPI/net472/PublicAPI.Unshipped.txt
#	src/Microsoft.IdentityModel.Tokens/PublicAPI/net6.0/PublicAPI.Unshipped.txt
#	src/Microsoft.IdentityModel.Tokens/PublicAPI/net8.0/PublicAPI.Unshipped.txt
#	src/Microsoft.IdentityModel.Tokens/PublicAPI/net9.0/PublicAPI.Unshipped.txt
#	src/Microsoft.IdentityModel.Tokens/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
Remove non-ML-DSA entries that were incorrectly added during the
dev8x merge conflict resolution. The file should only contain our
new internal API entries, not entries already tracked in
InternalAPI.Shipped.txt.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The ML-DSA entries are identical across all TFMs. Move them to the
root PublicAPI.Unshipped.txt and empty the per-TFM files, matching
the repo convention.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/Microsoft.IdentityModel.Tokens/X509SecurityKey.cs
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.

4 participants