The PQ signature check fails
X509Chain.Build(certificate, CryptoMode.Hybrid) returns false even though ChainStatus reports no
error. Or the validation throws a CryptographicException, for example:
Certificate 'CN=signer.example.com' is signed with ML-DSA, but its issuer 'CN=Contoso PQ Root CA' has no ML-DSA subject key.
Environment
All targets. Chain validation with CryptoMode.Hybrid or CryptoMode.PostQuantum is affected.
Cause
In a PQ mode, the library first validates the chain the way .NET does, and then verifies each certificate's ML-DSA signature with its issuer's ML-DSA key. The results mean the following:
| Result | Meaning |
|---|---|
false, with a reason in ChainStatus | The classical .NET validation failed, for example because of an unknown root certificate. The PQ signatures weren't checked. |
false, with no error in ChainStatus | At least one ML-DSA signature is invalid. Either the certificate changed after it was issued, or the issuer in the chain isn't the one that signed it. |
CryptographicException | The PQ part can't be verified: a certificate in the chain doesn't carry an ML-DSA signature, or its issuer lacks the ML-DSA key. The library treats this neither as valid nor silently as invalid. |
On Linux, even the classical validation of a chain with a pure ML-DSA issuer can fail if .NET loads a
libcrypto without ML-DSA.
Resolution
Read the validation report. It lists the PQ signature status of each certificate:
if (!chain.Build(certificate, CryptoMode.Hybrid)) { foreach (var element in chain.GetValidationReport().Elements) { Console.WriteLine($"{element.Subject}: {element.PqSignatureStatus}"); } }
Invalidfor a certificate: Reissue it. An invalid signature can't be repaired.- An exception because a signature is missing: The chain contains a classical-only certificate. Validate that chain with
CryptoMode.Classic, or replace the certificate with a hybrid one. - On Linux: Have .NET load OpenSSL 3.5 or later as well, as described in Configure OpenSSL.
en/wiki/pqcrypt/lib/troubleshooting/pq-signature-check-fails.txt · Last modified: by Wolfgang van der Stille