Namespace: WvdS.System.Security.Cryptography.Encryption
Classe statica per la crittografia AES-GCM con supporto per chiavi Post-Quantum. Supporta crittografia classica, ibrida e puramente PQ.
Questa classe offre tre approcci di crittografia:
| Modalita | Classico | ML-KEM | Utilizzo |
| Classic | RSA-OAEP / ECDH | - | Comportamento standard .NET |
| Hybrid | RSA-OAEP / ECDH | ✓ | Massima sicurezza |
| PostQuantum | - | ✓ | Puramente post-quantum |
Crittografa i dati con AES-GCM utilizzando un Shared Secret ML-KEM.
// Shared Secret da ML-KEM Key Exchange byte[] sharedSecret = session.SharedSecret; // Crittografare byte[] plaintext = Encoding.UTF8.GetBytes("Messaggio segreto"); byte[] encrypted = SymmetricEncryptionExtensions.EncryptWithPqKey( plaintext, sharedSecret); // Con Additional Authenticated Data (AAD) byte[] aad = Encoding.UTF8.GetBytes("Info-contesto"); byte[] encryptedWithAad = SymmetricEncryptionExtensions.EncryptWithPqKey( plaintext, sharedSecret, associatedData: aad);
byte[] decrypted = SymmetricEncryptionExtensions.DecryptWithPqKey( encrypted, sharedSecret, associatedData: aad); // Se usato durante Encrypt string message = Encoding.UTF8.GetString(decrypted);
Combina RSA-OAEP Key Encapsulation con ML-KEM per crittografia ibrida quantum-sicura.
using var rsa = RSA.Create(4096); var (mlKemPublicKey, mlKemPrivateKey) = PqCrypto.GenerateKeyPair(); byte[] plaintext = GetSecretData(); // Crittografia ibrida (RSA + ML-KEM) HybridEncryptedData encrypted = SymmetricEncryptionExtensions.EncryptHybrid( plaintext, rsa, // Chiave pubblica RSA del destinatario mlKemPublicKey, // Chiave pubblica ML-KEM del destinatario CryptoMode.Hybrid); // Serializzare per il trasporto byte[] serialized = encrypted.ToBytes();
// Deserializzare HybridEncryptedData encrypted = HybridEncryptedData.FromBytes(serialized); // Decrittografare byte[] plaintext = SymmetricEncryptionExtensions.DecryptHybrid( encrypted, rsaPrivateKey, // Chiave privata RSA mlKemPrivateKey); // Chiave privata ML-KEM
Crittografia stile ECIES con ECDH effimero e ML-KEM.
using var recipientEcdh = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP384); var (mlKemPublicKey, mlKemPrivateKey) = PqCrypto.GenerateKeyPair(); byte[] plaintext = GetSecretData(); // Crittografia ibrida ECDH + ML-KEM HybridEncryptedData encrypted = SymmetricEncryptionExtensions.EncryptEcdhPq( plaintext, recipientEcdh, // Chiave pubblica ECDH del destinatario mlKemPublicKey, // Chiave pubblica ML-KEM CryptoMode.Hybrid); // La chiave pubblica ECDH effimera e contenuta in encrypted.EphemeralPublicKey
byte[] plaintext = SymmetricEncryptionExtensions.DecryptEcdhPq( encrypted, recipientEcdhPrivateKey, mlKemPrivateKey);
Crittografia AES-256-GCM diretta senza Key Encapsulation.
byte[] key = RandomNumberGenerator.GetBytes(32); // Chiave 256-bit byte[] plaintext = GetData(); // AES-GCM standard byte[] encrypted = SymmetricEncryptionExtensions.EncryptAesGcm( plaintext, key); // Con AAD byte[] aad = Encoding.UTF8.GetBytes("message-context"); byte[] encryptedWithAad = SymmetricEncryptionExtensions.EncryptAesGcm( plaintext, key, associatedData: aad);
Formato di output:
┌─────────────────────────────────────────┐ │ [12 Bytes] Nonce (generato casualmente) │ │ [n Bytes] Ciphertext │ │ [16 Bytes] GCM Authentication Tag │ └─────────────────────────────────────────┘
byte[] plaintext = SymmetricEncryptionExtensions.DecryptAesGcm( encrypted, key, associatedData: aad); // Se utilizzato
Per file di grandi dimensioni con elaborazione a chunk.
byte[] key = RandomNumberGenerator.GetBytes(32); using var inputStream = File.OpenRead("large-file.dat"); using var outputStream = File.Create("large-file.enc"); SymmetricEncryptionExtensions.EncryptStream( inputStream, outputStream, key, chunkSize: 64 * 1024); // Chunk da 64 KB (predefinito)
Formato chunk:
┌────────────────────────────────────────────┐ │ [12 Bytes] Base Nonce │ ├────────────────────────────────────────────┤ │ Chunk 0: │ │ [4 Bytes] Lunghezza chunk │ │ [n Bytes] Dati crittografati │ │ [16 Bytes] GCM Tag │ ├────────────────────────────────────────────┤ │ Chunk 1: (Nonce = Base + 1) │ │ [4 Bytes] Lunghezza chunk │ │ [n Bytes] Dati crittografati │ │ [16 Bytes] GCM Tag │ ├────────────────────────────────────────────┤ │ ... altri chunk ... │ ├────────────────────────────────────────────┤ │ [4 Bytes] Marcatore di fine (0x00000000) │ └────────────────────────────────────────────┘
using var inputStream = File.OpenRead("large-file.enc"); using var outputStream = File.Create("large-file.decrypted"); SymmetricEncryptionExtensions.DecryptStream( inputStream, outputStream, key);
Deriva una chiave AES-256 da un Shared Secret.
byte[] sharedSecret = GetMlKemSharedSecret(); // Derivazione standard byte[] aesKey = SymmetricEncryptionExtensions.DeriveAesKey(sharedSecret); // Con Salt e Info byte[] salt = RandomNumberGenerator.GetBytes(32); byte[] info = Encoding.UTF8.GetBytes("MyApp-Encryption-Key"); byte[] aesKeyCustom = SymmetricEncryptionExtensions.DeriveAesKey( sharedSecret, salt: salt, info: info);
Implementazione interna: HKDF-SHA256 con info=„WvdS-PQ-AES-Key“
Deriva piu chiavi per scopi diversi.
byte[] sharedSecret = GetMlKemSharedSecret(); var (encryptionKey, macKey, iv) = SymmetricEncryptionExtensions.DeriveMultipleKeys( sharedSecret, salt: optionalSalt); // encryptionKey: 32 Bytes (AES-256) // macKey: 32 Bytes (HMAC) // iv: 16 Bytes (Vettore di inizializzazione)
Contenitore per dati crittografati ibridi con serializzazione.
| Proprieta | Tipo | Descrizione |
|---|---|---|
Mode | CryptoMode | Modalita di crittografia utilizzata |
ClassicEncapsulatedKey | byte[]? | Chiave contenuto crittografata RSA |
EphemeralPublicKey | byte[]? | Chiave pubblica ECDH effimera |
PqCiphertext | byte[]? | Ciphertext ML-KEM |
EncryptedContent | byte[] | Dati crittografati AES-GCM |
HybridEncryptedData encrypted = EncryptData(); // A byte array byte[] serialized = encrypted.ToBytes(); // Da byte array HybridEncryptedData restored = HybridEncryptedData.FromBytes(serialized);
API semplificata per crittografia puramente PQ.
// Generare coppia di chiavi var (publicKey, privateKey) = PqCrypto.GenerateKeyPair(); // Crittografare byte[] plaintext = Encoding.UTF8.GetBytes("Messaggio segreto"); var (ciphertext, encryptedData) = PqCrypto.Encrypt(plaintext, publicKey); // Decrittografare byte[] decrypted = PqCrypto.Decrypt(ciphertext, encryptedData, privateKey);
| Metodo | Parametri | Ritorno |
|---|---|---|
EncryptWithPqKey | byte[] plaintext, byte[] sharedSecret, byte[]? aad | byte[] |
DecryptWithPqKey | byte[] ciphertext, byte[] sharedSecret, byte[]? aad | byte[] |
EncryptHybrid | byte[] plaintext, RSA pubKey, byte[] pqPubKey, CryptoMode? | HybridEncryptedData |
DecryptHybrid | HybridEncryptedData, RSA privKey, byte[] pqPrivKey | byte[] |
EncryptEcdhPq | byte[] plaintext, ECDiffieHellman pubKey, byte[] pqPubKey, CryptoMode? | HybridEncryptedData |
DecryptEcdhPq | HybridEncryptedData, ECDiffieHellman privKey, byte[] pqPrivKey | byte[] |
EncryptAesGcm | byte[] plaintext, byte[] key, byte[]? aad | byte[] |
DecryptAesGcm | byte[] ciphertext, byte[] key, byte[]? aad | byte[] |
EncryptStream | Stream input, Stream output, byte[] key, int chunkSize | void |
DecryptStream | Stream input, Stream output, byte[] key | void |
DeriveAesKey | byte[] sharedSecret, byte[]? salt, byte[]? info | byte[] |
DeriveMultipleKeys | byte[] sharedSecret, byte[]? salt | (byte[], byte[], byte[]) |
| Metodo | Parametri | Ritorno |
|---|---|---|
GenerateKeyPair | - | (byte[] PublicKey, byte[] PrivateKey) |
Encrypt | byte[] plaintext, byte[] recipientPublicKey | (byte[] Ciphertext, byte[] EncryptedData) |
Decrypt | byte[] ciphertext, byte[] encryptedData, byte[] privateKey | byte[] |
using WvdS.System.Security.Cryptography; using WvdS.System.Security.Cryptography.Encryption; // 1. Generare chiavi (Destinatario) using var rsa = RSA.Create(4096); var (mlKemPublicKey, mlKemPrivateKey) = PqCrypto.GenerateKeyPair(); // 2. Trasmettere le chiavi pubbliche al mittente // (In pratica: Certificato con chiavi PQ incorporate) // --- Mittente --- // 3. Crittografare messaggio byte[] message = File.ReadAllBytes("document.pdf"); HybridEncryptedData encrypted = SymmetricEncryptionExtensions.EncryptHybrid( message, rsa, // Chiave pubblica RSA del destinatario mlKemPublicKey, // Chiave pubblica ML-KEM del destinatario CryptoMode.Hybrid); // 4. Serializzare e inviare byte[] package = encrypted.ToBytes(); File.WriteAllBytes("document.encrypted", package); // --- Destinatario --- // 5. Ricevere e deserializzare byte[] receivedPackage = File.ReadAllBytes("document.encrypted"); HybridEncryptedData receivedData = HybridEncryptedData.FromBytes(receivedPackage); // 6. Decrittografare byte[] decrypted = SymmetricEncryptionExtensions.DecryptHybrid( receivedData, rsa, // Propria chiave privata RSA mlKemPrivateKey); // Propria chiave privata ML-KEM File.WriteAllBytes("document.decrypted.pdf", decrypted);
DeriveAesKey senza Salt e deterministico - solo per casi d'uso specificiCombined Key = HKDF-SHA256(
ikm = classicSecret || pqSecret,
info = "WvdS-Hybrid-Key"
)
Anche se un attaccante compromette il secret classico, la crittografia rimane protetta dal secret PQ (e viceversa).
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional