====== SignatureExtensions ======
**Namespace:** ''WvdS.System.Security.Cryptography.Signatures''
Drop-in replacement extensions for digital signatures with Post-Quantum support. Extends ''RSA'', ''ECDsa'' and ''X509Certificate2'' with PQ-hybrid signing functions.
===== Overview =====
This class provides three types of signatures:
| Mode | Classical | ML-DSA | Usage |
| Classic | ✓ | - | Standard .NET behavior |
| Hybrid | ✓ | ✓ | Maximum security |
| PostQuantum | - | ✓ | Pure post-quantum |
===== RSA SignData/VerifyData =====
using var rsa = RSA.Create(2048);
byte[] data = Encoding.UTF8.GetBytes("Important data");
// Sign with explicit mode
byte[] signature = rsa.SignData(
data,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1,
CryptoMode.Hybrid);
// Verify
bool isValid = rsa.VerifyData(
data,
signature,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1,
CryptoMode.Hybrid);
==== Stream Signature ====
using var fileStream = File.OpenRead("document.pdf");
byte[] signature = rsa.SignData(
fileStream,
HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1,
CryptoMode.Hybrid);
===== ECDsa SignData/VerifyData =====
using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);
byte[] data = GetDataToSign();
// Sign
byte[] signature = ecdsa.SignData(
data,
HashAlgorithmName.SHA256,
CryptoMode.Hybrid);
// Verify
bool isValid = ecdsa.VerifyData(
data,
signature,
HashAlgorithmName.SHA256,
CryptoMode.Hybrid);
===== Certificate-based Signatures =====
var certificate = GetSigningCertificate();
byte[] data = GetDataToSign();
// Sign (automatically uses RSA or ECDSA)
byte[] signature = certificate.SignData(
data,
HashAlgorithmName.SHA256,
CryptoMode.Hybrid);
// Verify
bool isValid = certificate.VerifyData(
data,
signature,
HashAlgorithmName.SHA256,
CryptoMode.Hybrid);
The key type is automatically detected:
* RSA certificate -> RSA.SignData + ML-DSA
* ECDSA certificate -> ECDsa.SignData + ML-DSA
===== Standalone ML-DSA =====
Direct ML-DSA signatures without classical key:
// Generate key pair
var (publicKey, privateKey) = SignatureExtensions.GenerateMlDsaKeyPair();
// Sign
byte[] data = GetDataToSign();
byte[] signature = SignatureExtensions.SignMlDsa(data, privateKey);
// Verify
bool isValid = SignatureExtensions.VerifyMlDsa(data, signature, publicKey);
===== Hybrid Signature Format =====
+---------------------------------------------+
| [4 Bytes] Classical signature length |
| [n Bytes] Classical signature (RSA/ECDSA) |
| [m Bytes] PQ signature (ML-DSA-65) |
+---------------------------------------------+
^ Component ^ Typical Size ^
| Length field | 4 bytes |
| RSA-2048 signature | 256 bytes |
| ECDSA P-256 signature | ~70 bytes |
| ML-DSA-65 signature | 3,293 bytes |
| **Hybrid RSA** | **~3,553 bytes** |
| **Hybrid ECDSA** | **~3,367 bytes** |
===== Transient PQ Keys =====
For standalone signatures (without certificate), thread-local transient keys are used:
// Set own keys
var (pubKey, privKey) = SignatureExtensions.GenerateMlDsaKeyPair();
SignatureExtensions.SetTransientPqKey(pubKey, privKey);
// Now SignData/VerifyData can be used without certificate
byte[] sig = rsa.SignData(data, HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1, CryptoMode.Hybrid);
// Only public key for verification
SignatureExtensions.SetTransientPqPublicKey(pubKey);
bool valid = rsa.VerifyData(data, sig, HashAlgorithmName.SHA256,
RSASignaturePadding.Pkcs1, CryptoMode.Hybrid);
// Cleanup (overwrites private key with zeros)
SignatureExtensions.ClearTransientPqKey();
===== Methods Overview =====
==== RSA Extensions ====
^ Method ^ Parameters ^ Return ^
| ''SignData(data, hash, padding, mode)'' | byte[], HashAlgorithmName, RSASignaturePadding, CryptoMode? | byte[] |
| ''SignData(stream, hash, padding, mode)'' | Stream, HashAlgorithmName, RSASignaturePadding, CryptoMode? | byte[] |
| ''VerifyData(data, sig, hash, padding, mode)'' | byte[], byte[], HashAlgorithmName, RSASignaturePadding, CryptoMode? | bool |
==== ECDsa Extensions ====
^ Method ^ Parameters ^ Return ^
| ''SignData(data, hash, mode)'' | byte[], HashAlgorithmName, CryptoMode? | byte[] |
| ''SignData(stream, hash, mode)'' | Stream, HashAlgorithmName, CryptoMode? | byte[] |
| ''VerifyData(data, sig, hash, mode)'' | byte[], byte[], HashAlgorithmName, CryptoMode? | bool |
==== X509Certificate2 Extensions ====
^ Method ^ Parameters ^ Return ^
| ''SignData(data, hash, mode)'' | byte[], HashAlgorithmName, CryptoMode? | byte[] |
| ''VerifyData(data, sig, hash, mode)'' | byte[], byte[], HashAlgorithmName, CryptoMode? | bool |
==== Standalone ML-DSA ====
^ Method ^ Parameters ^ Return ^
| ''GenerateMlDsaKeyPair()'' | - | (byte[] PublicKey, byte[] PrivateKey) |
| ''SignMlDsa(data, privateKey)'' | byte[], byte[] | byte[] |
| ''VerifyMlDsa(data, sig, publicKey)'' | byte[], byte[], byte[] | bool |
==== Transient Key Management ====
^ Method ^ Description ^
| ''SetTransientPqKey(pub, priv)'' | Sets key pair for thread |
| ''SetTransientPqPublicKey(pub)'' | Sets only public key |
| ''ClearTransientPqKey()'' | Securely deletes keys |
===== Example: Complete Workflow =====
// 1. Configure CryptoMode
CryptoConfig.DefaultMode = CryptoMode.Hybrid;
// 2. Load certificate (with PQ keys)
var cert = X509Certificate2ExportExtensions.ImportPfx(
"signing-cert.pfx",
"password");
// 3. Sign document
byte[] documentData = File.ReadAllBytes("contract.pdf");
byte[] signature = cert.SignData(documentData, HashAlgorithmName.SHA256);
// 4. Save signature
File.WriteAllBytes("contract.sig", signature);
// 5. Verify later
var verifyCert = new X509Certificate2("signing-cert.cer");
bool isValid = verifyCert.VerifyData(
File.ReadAllBytes("contract.pdf"),
File.ReadAllBytes("contract.sig"),
HashAlgorithmName.SHA256);
Console.WriteLine($"Signature valid: {isValid}");
===== Security Notes =====
* In PostQuantum mode, no classical signature is created - not backward compatible
* Transient keys are stored thread-locally - do not share between threads
* Call ''ClearTransientPqKey()'' when keys are no longer needed
===== See Also =====
* [[.:start|Signatures Namespace]]
* [[.:signeddataextensions|SignedDataExtensions]]
* [[..:x509certificates:x509certificate2extensions|X509Certificate2Extensions]]
* [[en:int:pqcrypt:konzepte:algorithmen|ML-DSA Algorithm]]
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//