Sign CMS messages
You sign messages in CMS (PKCS #7) format, for example to exchange documents, and you want to include an ML-DSA signature next to the RSA or ECDSA signature without recipients that don't know about PQ rejecting the message.
Solution overview
| Element | Purpose |
|---|---|
SignedDataExtensions.CreatePqAwareSigner | creates a CmsSigner for a hybrid certificate and checks that its ML-DSA key is present |
SignedCms.ComputeSignature with CryptoMode.Hybrid | signs classically, announces the PQ signature in a signed attribute, and appends it |
SignedCms.CheckSignature with CryptoMode.Hybrid | verifies the classical signature as .NET does, then the PQ signature of each signer |
Implementation
Sign the message. Here, signerCertificate is a hybrid certificate with an RSA key whose ML-DSA key is in
the process. In this example, it's self-signed:
using var signerRsa = RSA.Create(3072); using var signerCertificate = new CertificateRequest( "CN=Contoso Accounting", signerRsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1) .CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(1), CryptoMode.Hybrid); var content = new ContentInfo("Invoice 2026-0042"u8.ToArray()); var outgoing = new SignedCms(content); outgoing.ComputeSignature(SignedDataExtensions.CreatePqAwareSigner(signerCertificate), CryptoMode.Hybrid); byte[] message = outgoing.Encode();
Verify the message at the recipient:
var incoming = new SignedCms(); incoming.Decode(message); incoming.CheckSignature(verifySignatureOnly: true, CryptoMode.Hybrid); Console.WriteLine("Both signatures are valid.");
Like the .NET method, CheckSignature returns nothing and throws a CryptographicException if a signature
is invalid.
Remarks
- Classical recipients. The PQ signature is in an unsigned attribute, and its announcement is in a signed attribute of the SignerInfo. Recipients without this library verify the message with the .NET
CheckSignaturelike any other. - Downgrades are detected. Anyone can remove an unsigned attribute. Because the classical signature protects the announcement,
CheckSignaturewithCryptoMode.Hybriddetects a removed PQ signature and throws aCryptographicException. It also rejects a PQ signature created with a key other than the announced one. - No on-the-fly key.
CreatePqAwareSignernever generates an ML-DSA key. If the certificate's key isn't in the process, the method throws aCryptographicExceptionright away. In that case, load the certificate from a PFX file, or use the overload that takes the key pair. - Provisional identifiers. The attributes use provisional identifiers; see Formats of the post-quantum parts.
- Certificate validation.
verifySignatureOnly: trueonly verifies the signatures. Withfalse, .NET also validates the signer certificate's chain according to the operating system's rules, without the PQ part. To validate the PQ part of the chain, useX509Chain.BuildwithCryptoMode.Hybrid.
Related topics
en/wiki/pqcrypt/lib/how-to/sign-cms-messages.txt · Zadnja sprememba: uporabnika Wolfgang van der Stille