====== SymmetricEncryptionExtensions ====== **Namespace:** ''WvdS.System.Security.Cryptography.Encryption'' Statische Klasse für AES-GCM Verschlüsselung mit Post-Quantum Key-Support. Unterstützt klassische, hybride und reine PQ-Verschlüsselung. ===== Übersicht ===== Diese Klasse bietet drei Verschlüsselungsansätze: | Modus | Klassisch | ML-KEM | Verwendung | | Classic | RSA-OAEP / ECDH | - | Standard .NET Verhalten | | Hybrid | RSA-OAEP / ECDH | ✓ | Maximale Sicherheit | | PostQuantum | - | ✓ | Rein post-quantum | ===== AES-GCM mit PQ-Key ===== ==== EncryptWithPqKey ==== Verschlüsselt Daten mit AES-GCM unter Verwendung eines ML-KEM Shared Secrets. // Shared Secret aus ML-KEM Key Exchange byte[] sharedSecret = session.SharedSecret; // Verschlüsseln byte[] plaintext = Encoding.UTF8.GetBytes("Geheime Nachricht"); byte[] encrypted = SymmetricEncryptionExtensions.EncryptWithPqKey( plaintext, sharedSecret); // Mit Additional Authenticated Data (AAD) byte[] aad = Encoding.UTF8.GetBytes("Kontext-Info"); byte[] encryptedWithAad = SymmetricEncryptionExtensions.EncryptWithPqKey( plaintext, sharedSecret, associatedData: aad); ==== DecryptWithPqKey ==== byte[] decrypted = SymmetricEncryptionExtensions.DecryptWithPqKey( encrypted, sharedSecret, associatedData: aad); // Falls bei Encrypt verwendet string message = Encoding.UTF8.GetString(decrypted); ===== Hybrid Encryption (RSA + ML-KEM) ===== Kombiniert RSA-OAEP Key Encapsulation mit ML-KEM für quantum-sichere hybride Verschlüsselung. ==== EncryptHybrid ==== using var rsa = RSA.Create(4096); var (mlKemPublicKey, mlKemPrivateKey) = PqCrypto.GenerateKeyPair(); byte[] plaintext = GetSecretData(); // Hybrid-Verschlüsselung (RSA + ML-KEM) HybridEncryptedData encrypted = SymmetricEncryptionExtensions.EncryptHybrid( plaintext, rsa, // RSA Public Key des Empfängers mlKemPublicKey, // ML-KEM Public Key des Empfängers CryptoMode.Hybrid); // Serialisieren für Transport byte[] serialized = encrypted.ToBytes(); ==== DecryptHybrid ==== // Deserialisieren HybridEncryptedData encrypted = HybridEncryptedData.FromBytes(serialized); // Entschlüsseln byte[] plaintext = SymmetricEncryptionExtensions.DecryptHybrid( encrypted, rsaPrivateKey, // RSA Private Key mlKemPrivateKey); // ML-KEM Private Key ===== ECDH + ML-KEM Encryption ===== ECIES-Style Verschlüsselung mit ephemerarem ECDH und ML-KEM. ==== EncryptEcdhPq ==== using var recipientEcdh = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP384); var (mlKemPublicKey, mlKemPrivateKey) = PqCrypto.GenerateKeyPair(); byte[] plaintext = GetSecretData(); // ECDH + ML-KEM Hybrid-Verschlüsselung HybridEncryptedData encrypted = SymmetricEncryptionExtensions.EncryptEcdhPq( plaintext, recipientEcdh, // ECDH Public Key des Empfängers mlKemPublicKey, // ML-KEM Public Key CryptoMode.Hybrid); // Ephemerer ECDH Public Key ist in encrypted.EphemeralPublicKey enthalten ==== DecryptEcdhPq ==== byte[] plaintext = SymmetricEncryptionExtensions.DecryptEcdhPq( encrypted, recipientEcdhPrivateKey, mlKemPrivateKey); ===== Core AES-GCM Operations ===== Direkte AES-256-GCM Verschlüsselung ohne Key Encapsulation. ==== EncryptAesGcm ==== byte[] key = RandomNumberGenerator.GetBytes(32); // 256-bit Key byte[] plaintext = GetData(); // Standard AES-GCM byte[] encrypted = SymmetricEncryptionExtensions.EncryptAesGcm( plaintext, key); // Mit AAD byte[] aad = Encoding.UTF8.GetBytes("message-context"); byte[] encryptedWithAad = SymmetricEncryptionExtensions.EncryptAesGcm( plaintext, key, associatedData: aad); **Ausgabeformat:** ┌─────────────────────────────────────────┐ │ [12 Bytes] Nonce (zufällig generiert) │ │ [n Bytes] Ciphertext │ │ [16 Bytes] GCM Authentication Tag │ └─────────────────────────────────────────┘ ==== DecryptAesGcm ==== byte[] plaintext = SymmetricEncryptionExtensions.DecryptAesGcm( encrypted, key, associatedData: aad); // Falls verwendet ===== Stream-basierte Verschlüsselung ===== Für große Dateien mit Chunk-basierter Verarbeitung. ==== EncryptStream ==== 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); // 64 KB Chunks (Standard) **Chunk-Format:** ┌────────────────────────────────────────────┐ │ [12 Bytes] Base Nonce │ ├────────────────────────────────────────────┤ │ Chunk 0: │ │ [4 Bytes] Chunk-Länge │ │ [n Bytes] Verschlüsselte Daten │ │ [16 Bytes] GCM Tag │ ├────────────────────────────────────────────┤ │ Chunk 1: (Nonce = Base + 1) │ │ [4 Bytes] Chunk-Länge │ │ [n Bytes] Verschlüsselte Daten │ │ [16 Bytes] GCM Tag │ ├────────────────────────────────────────────┤ │ ... weitere Chunks ... │ ├────────────────────────────────────────────┤ │ [4 Bytes] End-Marker (0x00000000) │ └────────────────────────────────────────────┘ ==== DecryptStream ==== using var inputStream = File.OpenRead("large-file.enc"); using var outputStream = File.Create("large-file.decrypted"); SymmetricEncryptionExtensions.DecryptStream( inputStream, outputStream, key); ===== Key Derivation ===== ==== DeriveAesKey ==== Leitet einen AES-256 Key aus einem Shared Secret ab. byte[] sharedSecret = GetMlKemSharedSecret(); // Standard-Ableitung byte[] aesKey = SymmetricEncryptionExtensions.DeriveAesKey(sharedSecret); // Mit Salt und Info byte[] salt = RandomNumberGenerator.GetBytes(32); byte[] info = Encoding.UTF8.GetBytes("MyApp-Encryption-Key"); byte[] aesKeyCustom = SymmetricEncryptionExtensions.DeriveAesKey( sharedSecret, salt: salt, info: info); **Interne Implementierung:** HKDF-SHA256 mit ''info="WvdS-PQ-AES-Key"'' ==== DeriveMultipleKeys ==== Leitet mehrere Schlüssel für verschiedene Zwecke ab. byte[] sharedSecret = GetMlKemSharedSecret(); var (encryptionKey, macKey, iv) = SymmetricEncryptionExtensions.DeriveMultipleKeys( sharedSecret, salt: optionalSalt); // encryptionKey: 32 Bytes (AES-256) // macKey: 32 Bytes (HMAC) // iv: 16 Bytes (Initialisierungsvektor) ===== HybridEncryptedData Klasse ===== Container für hybrid-verschlüsselte Daten mit Serialisierung. ==== Eigenschaften ==== ^ Eigenschaft ^ Typ ^ Beschreibung ^ | ''Mode'' | CryptoMode | Verwendeter Verschlüsselungsmodus | | ''ClassicEncapsulatedKey'' | byte[]? | RSA-verschlüsselter Content Key | | ''EphemeralPublicKey'' | byte[]? | Ephemerer ECDH Public Key | | ''PqCiphertext'' | byte[]? | ML-KEM Ciphertext | | ''EncryptedContent'' | byte[] | AES-GCM verschlüsselte Daten | ==== Serialisierung ==== HybridEncryptedData encrypted = EncryptData(); // Zu Byte-Array byte[] serialized = encrypted.ToBytes(); // Von Byte-Array HybridEncryptedData restored = HybridEncryptedData.FromBytes(serialized); ===== PqCrypto Convenience-Klasse ===== Vereinfachte API für reine PQ-Verschlüsselung. // Schlüsselpaar generieren var (publicKey, privateKey) = PqCrypto.GenerateKeyPair(); // Verschlüsseln byte[] plaintext = Encoding.UTF8.GetBytes("Geheime Nachricht"); var (ciphertext, encryptedData) = PqCrypto.Encrypt(plaintext, publicKey); // Entschlüsseln byte[] decrypted = PqCrypto.Decrypt(ciphertext, encryptedData, privateKey); ===== Methoden-Übersicht ===== ==== SymmetricEncryptionExtensions ==== ^ Methode ^ Parameter ^ Rückgabe ^ | ''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[]) | ==== PqCrypto ==== ^ Methode ^ Parameter ^ Rückgabe ^ | ''GenerateKeyPair'' | - | (byte[] PublicKey, byte[] PrivateKey) | | ''Encrypt'' | byte[] plaintext, byte[] recipientPublicKey | (byte[] Ciphertext, byte[] EncryptedData) | | ''Decrypt'' | byte[] ciphertext, byte[] encryptedData, byte[] privateKey | byte[] | ===== Vollständiges Beispiel ===== using WvdS.System.Security.Cryptography; using WvdS.System.Security.Cryptography.Encryption; // 1. Schlüssel generieren (Empfänger) using var rsa = RSA.Create(4096); var (mlKemPublicKey, mlKemPrivateKey) = PqCrypto.GenerateKeyPair(); // 2. Public Keys an Sender übermitteln // (In Praxis: Zertifikat mit eingebetteten PQ-Keys) // --- Sender --- // 3. Nachricht verschlüsseln byte[] message = File.ReadAllBytes("document.pdf"); HybridEncryptedData encrypted = SymmetricEncryptionExtensions.EncryptHybrid( message, rsa, // Empfänger RSA Public Key mlKemPublicKey, // Empfänger ML-KEM Public Key CryptoMode.Hybrid); // 4. Serialisieren und senden byte[] package = encrypted.ToBytes(); File.WriteAllBytes("document.encrypted", package); // --- Empfänger --- // 5. Empfangen und deserialisieren byte[] receivedPackage = File.ReadAllBytes("document.encrypted"); HybridEncryptedData receivedData = HybridEncryptedData.FromBytes(receivedPackage); // 6. Entschlüsseln byte[] decrypted = SymmetricEncryptionExtensions.DecryptHybrid( receivedData, rsa, // Eigener RSA Private Key mlKemPrivateKey); // Eigener ML-KEM Private Key File.WriteAllBytes("document.decrypted.pdf", decrypted); ===== Sicherheitshinweise ===== * AES-GCM Nonces dürfen NIEMALS wiederverwendet werden * Bei Hybrid-Modus wird Key aus klassischem UND PQ-Secret abgeleitet * ''DeriveAesKey'' ohne Salt ist deterministisch - nur für spezifische Anwendungsfälle * Stream-Verschlüsselung verwendet inkrementelle Nonces pro Chunk **Key-Kombinierung im Hybrid-Modus:** Combined Key = HKDF-SHA256( ikm = classicSecret || pqSecret, info = "WvdS-Hybrid-Key" ) Selbst wenn ein Angreifer das klassische Secret kompromittiert, bleibt die Verschlüsselung durch das PQ-Secret geschützt (und umgekehrt). ===== Siehe auch ===== * [[.:start|Encryption Namespace]] * [[.:hybridencrypteddata|HybridEncryptedData]] * [[.:pqcrypto|PqCrypto]] * [[..:keyexchange:start|KeyExchange Namespace]] * [[..:keyderivation:start|KeyDerivation Namespace]] * [[de:int:pqcrypt:konzepte:algorithmen:ml-kem|ML-KEM Algorithmus]] ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//