Inhaltsverzeichnis

SignatureExtensions

Namespace: WvdS.System.Security.Cryptography.Signatures

Drop-In Replacement proširenja za digitalne potpise s Post-Quantum podrškom. Proširuje RSA, ECDsa i X509Certificate2 s PQ-hibridnim funkcijama potpisivanja.

Pregled

Ova klasa nudi tri vrste potpisa:

Način Klasični ML-DSA Uporaba
Classic - Standardno .NET ponašanje
Hybrid Maksimalna sigurnost
PostQuantum - Čisto post-quantum

RSA SignData/VerifyData

using var rsa = RSA.Create(2048);
byte[] data = Encoding.UTF8.GetBytes("Važni podaci");
 
// Potpisivanje s eksplicitnim načinom
byte[] signature = rsa.SignData(
    data,
    HashAlgorithmName.SHA256,
    RSASignaturePadding.Pkcs1,
    CryptoMode.Hybrid);
 
// Verifikacija
bool isValid = rsa.VerifyData(
    data,
    signature,
    HashAlgorithmName.SHA256,
    RSASignaturePadding.Pkcs1,
    CryptoMode.Hybrid);

Stream potpis

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();
 
// Potpisivanje
byte[] signature = ecdsa.SignData(
    data,
    HashAlgorithmName.SHA256,
    CryptoMode.Hybrid);
 
// Verifikacija
bool isValid = ecdsa.VerifyData(
    data,
    signature,
    HashAlgorithmName.SHA256,
    CryptoMode.Hybrid);

Potpisi temeljeni na certifikatu

var certificate = GetSigningCertificate();
byte[] data = GetDataToSign();
 
// Potpisivanje (automatski koristi RSA ili ECDSA)
byte[] signature = certificate.SignData(
    data,
    HashAlgorithmName.SHA256,
    CryptoMode.Hybrid);
 
// Verifikacija
bool isValid = certificate.VerifyData(
    data,
    signature,
    HashAlgorithmName.SHA256,
    CryptoMode.Hybrid);

Tip ključa se automatski prepoznaje:

Samostalni ML-DSA

Direktni ML-DSA potpisi bez klasičnog ključa:

// Generiranje para ključeva
var (publicKey, privateKey) = SignatureExtensions.GenerateMlDsaKeyPair();
 
// Potpisivanje
byte[] data = GetDataToSign();
byte[] signature = SignatureExtensions.SignMlDsa(data, privateKey);
 
// Verifikacija
bool isValid = SignatureExtensions.VerifyMlDsa(data, signature, publicKey);

Format hibridnog potpisa

┌────────────────────────────────────────────┐
│ [4 bajta] Duljina klasičnog potpisa         │
│ [n bajtova] Klasični potpis (RSA/ECDSA)     │
│ [m bajtova] PQ potpis (ML-DSA-65)           │
└────────────────────────────────────────────┘
Komponenta Tipična veličina
Polje duljine 4 bajta
RSA-2048 potpis 256 bajtova
ECDSA P-256 potpis ~70 bajtova
ML-DSA-65 potpis 3.293 bajta
Hibridni RSA ~3.553 bajta
Hibridni ECDSA ~3.367 bajtova

Prolazni PQ ključevi

Za samostalne potpise (bez certifikata) koriste se thread-lokalni prolazni ključevi:

// Postavljanje vlastitih ključeva
var (pubKey, privKey) = SignatureExtensions.GenerateMlDsaKeyPair();
SignatureExtensions.SetTransientPqKey(pubKey, privKey);
 
// Sada se SignData/VerifyData mogu koristiti bez certifikata
byte[] sig = rsa.SignData(data, HashAlgorithmName.SHA256,
    RSASignaturePadding.Pkcs1, CryptoMode.Hybrid);
 
// Samo javni ključ za verifikaciju
SignatureExtensions.SetTransientPqPublicKey(pubKey);
bool valid = rsa.VerifyData(data, sig, HashAlgorithmName.SHA256,
    RSASignaturePadding.Pkcs1, CryptoMode.Hybrid);
 
// Čišćenje (prepisuje privatni ključ nulama)
SignatureExtensions.ClearTransientPqKey();

Pregled metoda

RSA proširenja

Metoda Parametri Povratni tip
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 proširenja

Metoda Parametri Povratni tip
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 proširenja

Metoda Parametri Povratni tip
SignData(data, hash, mode) byte[], HashAlgorithmName, CryptoMode? byte[]
VerifyData(data, sig, hash, mode) byte[], byte[], HashAlgorithmName, CryptoMode? bool

Samostalni ML-DSA

Metoda Parametri Povratni tip
GenerateMlDsaKeyPair() - (byte[] PublicKey, byte[] PrivateKey)
SignMlDsa(data, privateKey) byte[], byte[] byte[]
VerifyMlDsa(data, sig, publicKey) byte[], byte[], byte[] bool

Upravljanje prolaznim ključevima

Metoda Opis
SetTransientPqKey(pub, priv) Postavlja par ključeva za thread
SetTransientPqPublicKey(pub) Postavlja samo javni ključ
ClearTransientPqKey() Sigurno briše ključeve

Primjer: Potpuni tijek rada

// 1. Konfiguriranje CryptoMode
CryptoConfig.DefaultMode = CryptoMode.Hybrid;
 
// 2. Učitavanje certifikata (s PQ ključevima)
var cert = X509Certificate2ExportExtensions.ImportPfx(
    "signing-cert.pfx",
    "password");
 
// 3. Potpisivanje dokumenta
byte[] documentData = File.ReadAllBytes("contract.pdf");
byte[] signature = cert.SignData(documentData, HashAlgorithmName.SHA256);
 
// 4. Spremanje potpisa
File.WriteAllBytes("contract.sig", signature);
 
// 5. Kasnija verifikacija
var verifyCert = new X509Certificate2("signing-cert.cer");
bool isValid = verifyCert.VerifyData(
    File.ReadAllBytes("contract.pdf"),
    File.ReadAllBytes("contract.sig"),
    HashAlgorithmName.SHA256);
 
Console.WriteLine($"Potpis valjan: {isValid}");

Sigurnosne napomene

  • U PostQuantum načinu ne stvara se klasični potpis - nije unatrag kompatibilno
  • Prolazni ključevi se pohranjuju thread-lokalno - ne dijeliti između niti
  • Pozvati ClearTransientPqKey() kada ključevi više nisu potrebni

Vidi također


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional