====== 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//