~~NOTOC~~ ====== Szenario 7.3: Dateiverschlüsselung ====== **Kategorie:** [[.:start|Verschlüsselung]] \\ **Komplexität:** ⭐⭐⭐ (Mittel) \\ **Voraussetzungen:** Schlüsselmaterial oder Passwort \\ **Geschätzte Zeit:** 15-20 Minuten ---- ===== Beschreibung ===== Dieses Szenario beschreibt die **sichere Verschlüsselung von Dateien** mit Post-Quantum-sicheren Verfahren. Die Implementierung unterstützt sowohl passwortbasierte als auch schlüsselbasierte Verschlüsselung. **Anwendungsfälle:** * Backup-Verschlüsselung * Dokumentenschutz * Konfigurationsdateien * Archivierung ---- ===== Workflow ===== flowchart TD FILE[Originaldatei] --> COMPRESS[Optional: Komprimieren] COMPRESS --> CHUNK[In Chunks aufteilen] CHUNK --> ENCRYPT[AES-256-GCM pro Chunk] subgraph Key Derivation PWD[Passwort] --> KDF[Argon2id] KDF --> KEY[Encryption Key] end KEY --> ENCRYPT ENCRYPT --> OUTPUT[Verschlüsselte Datei] style KEY fill:#e8f5e9 style OUTPUT fill:#e3f2fd ---- ===== Code-Beispiel: Datei verschlüsseln ===== using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using System.Security.Cryptography; using var ctx = PqCryptoContext.Initialize(); // Quelldatei string inputFile = "document.pdf"; string outputFile = "document.pdf.enc"; string password = "MySecurePassword123!"; // Verschlüsselungsparameter var salt = RandomNumberGenerator.GetBytes(32); var nonce = RandomNumberGenerator.GetBytes(12); // Schlüssel aus Passwort ableiten (Argon2id) var key = ctx.DeriveKeyArgon2id( password: Encoding.UTF8.GetBytes(password), salt: salt, outputLength: 32, iterations: 3, memoryKiB: 65536, // 64 MB parallelism: 4 ); // Datei einlesen var plaintext = File.ReadAllBytes(inputFile); // Verschlüsseln mit AES-256-GCM var ciphertext = new byte[plaintext.Length]; var tag = new byte[16]; using var aes = new OpenSslAesGcm(key); aes.Encrypt(nonce, plaintext, ciphertext, tag); // Header + Ciphertext schreiben using var output = File.Create(outputFile); using var writer = new BinaryWriter(output); // Magic number writer.Write(Encoding.ASCII.GetBytes("PQENC")); // Version writer.Write((byte)1); // Salt writer.Write(salt.Length); writer.Write(salt); // Nonce writer.Write(nonce.Length); writer.Write(nonce); // Tag writer.Write(tag.Length); writer.Write(tag); // Ciphertext writer.Write(ciphertext.Length); writer.Write(ciphertext); Console.WriteLine($"Datei verschlüsselt: {outputFile}"); Console.WriteLine($" Original: {plaintext.Length:N0} Bytes"); Console.WriteLine($" Verschlüsselt: {output.Length:N0} Bytes"); ---- ===== Code-Beispiel: Datei entschlüsseln ===== using var ctx = PqCryptoContext.Initialize(); string encryptedFile = "document.pdf.enc"; string outputFile = "document-decrypted.pdf"; string password = "MySecurePassword123!"; using var input = File.OpenRead(encryptedFile); using var reader = new BinaryReader(input); // Magic number prüfen var magic = Encoding.ASCII.GetString(reader.ReadBytes(5)); if (magic != "PQENC") throw new InvalidDataException("Ungültiges Dateiformat"); // Version prüfen var version = reader.ReadByte(); if (version != 1) throw new NotSupportedException($"Version {version} nicht unterstützt"); // Parameter lesen var saltLen = reader.ReadInt32(); var salt = reader.ReadBytes(saltLen); var nonceLen = reader.ReadInt32(); var nonce = reader.ReadBytes(nonceLen); var tagLen = reader.ReadInt32(); var tag = reader.ReadBytes(tagLen); var ciphertextLen = reader.ReadInt32(); var ciphertext = reader.ReadBytes(ciphertextLen); // Schlüssel ableiten (gleiche Parameter!) var key = ctx.DeriveKeyArgon2id( password: Encoding.UTF8.GetBytes(password), salt: salt, outputLength: 32, iterations: 3, memoryKiB: 65536, parallelism: 4 ); // Entschlüsseln var plaintext = new byte[ciphertext.Length]; using var aes = new OpenSslAesGcm(key); aes.Decrypt(nonce, ciphertext, tag, plaintext); // Speichern File.WriteAllBytes(outputFile, plaintext); Console.WriteLine($"Datei entschlüsselt: {outputFile}"); ---- ===== Streaming für große Dateien ===== public class FileEncryptor { private const int ChunkSize = 64 * 1024; // 64 KB chunks public void EncryptLargeFile( string inputPath, string outputPath, byte[] key) { using var ctx = PqCryptoContext.Initialize(); using var input = File.OpenRead(inputPath); using var output = File.Create(outputPath); using var writer = new BinaryWriter(output); // Header schreiben writer.Write(Encoding.ASCII.GetBytes("PQENC")); writer.Write((byte)2); // Version 2 = Streaming // Anzahl Chunks var totalChunks = (int)Math.Ceiling((double)input.Length / ChunkSize); writer.Write(totalChunks); var buffer = new byte[ChunkSize]; var chunkIndex = 0; while (input.Position < input.Length) { var bytesRead = input.Read(buffer, 0, ChunkSize); var chunk = buffer.AsSpan(0, bytesRead).ToArray(); // Eindeutige Nonce pro Chunk (ChunkIndex + Random) var nonce = new byte[12]; BitConverter.GetBytes(chunkIndex).CopyTo(nonce, 0); RandomNumberGenerator.Fill(nonce.AsSpan(4)); var ciphertext = new byte[bytesRead]; var tag = new byte[16]; using var aes = new OpenSslAesGcm(key); // AAD = Chunk-Index für Reihenfolge-Schutz var aad = BitConverter.GetBytes(chunkIndex); aes.Encrypt(nonce, chunk, ciphertext, tag, aad); // Chunk schreiben writer.Write(nonce); writer.Write(tag); writer.Write(ciphertext.Length); writer.Write(ciphertext); chunkIndex++; } Console.WriteLine($"Verschlüsselt: {chunkIndex} Chunks"); } public void DecryptLargeFile( string inputPath, string outputPath, byte[] key) { using var input = File.OpenRead(inputPath); using var reader = new BinaryReader(input); using var output = File.Create(outputPath); // Header lesen var magic = Encoding.ASCII.GetString(reader.ReadBytes(5)); if (magic != "PQENC") throw new InvalidDataException(); var version = reader.ReadByte(); if (version != 2) throw new NotSupportedException(); var totalChunks = reader.ReadInt32(); for (int i = 0; i < totalChunks; i++) { var nonce = reader.ReadBytes(12); var tag = reader.ReadBytes(16); var ciphertextLen = reader.ReadInt32(); var ciphertext = reader.ReadBytes(ciphertextLen); var plaintext = new byte[ciphertextLen]; using var aes = new OpenSslAesGcm(key); var aad = BitConverter.GetBytes(i); aes.Decrypt(nonce, ciphertext, tag, plaintext, aad); output.Write(plaintext); } } } ---- ===== Hybrid-Verschlüsselung mit ML-KEM ===== public class HybridFileEncryptor { public void EncryptForRecipient( string inputPath, string outputPath, byte[] recipientMlKemPublicKey) { using var ctx = PqCryptoContext.Initialize(); // ML-KEM Key Encapsulation var pubKey = ctx.ImportPublicKey(recipientMlKemPublicKey); var (kemCiphertext, sharedSecret) = ctx.Encapsulate(pubKey); // File Encryption Key ableiten var fileKey = ctx.DeriveKey( sharedSecret, outputLength: 32, info: Encoding.UTF8.GetBytes("file-encryption-key") ); // Datei verschlüsseln var encryptor = new FileEncryptor(); var tempFile = Path.GetTempFileName(); encryptor.EncryptLargeFile(inputPath, tempFile, fileKey); // Output mit KEM Ciphertext using var output = File.Create(outputPath); using var writer = new BinaryWriter(output); writer.Write(Encoding.ASCII.GetBytes("PQKEM")); writer.Write((byte)1); writer.Write(kemCiphertext.Length); writer.Write(kemCiphertext); // Verschlüsselte Datei anhängen using var encryptedContent = File.OpenRead(tempFile); encryptedContent.CopyTo(output); File.Delete(tempFile); } } ---- ===== Dateiformat-Spezifikation ===== PQENC v1 (Single-Shot): ┌─────────────────────────────────┐ │ Magic: "PQENC" (5 bytes) │ │ Version: 0x01 (1 byte) │ │ Salt Length (4 bytes) │ │ Salt (variable) │ │ Nonce Length (4 bytes) │ │ Nonce (12 bytes) │ │ Tag Length (4 bytes) │ │ Tag (16 bytes) │ │ Ciphertext Length (4 bytes) │ │ Ciphertext (variable) │ └─────────────────────────────────┘ PQENC v2 (Streaming): ┌─────────────────────────────────┐ │ Magic: "PQENC" (5 bytes) │ │ Version: 0x02 (1 byte) │ │ Total Chunks (4 bytes) │ ├─────────────────────────────────┤ │ Chunk 0: │ │ Nonce (12 bytes) │ │ Tag (16 bytes) │ │ Ciphertext Length (4 bytes) │ │ Ciphertext (variable) │ ├─────────────────────────────────┤ │ Chunk 1: ... │ └─────────────────────────────────┘ ---- ===== Verwandte Szenarien ===== ^ Beziehung ^ Szenario ^ Beschreibung ^ | **Komponente** | [[.:key_encapsulation|7.2 Key Encapsulation]] | ML-KEM für Empfänger | | **Verwandt** | [[.:hybrid_encryption|7.1 Hybrid-Verschlüsselung]] | Hybrid-Konzept | | **Verwandt** | [[de:int:pqcrypt:szenarien:verwaltung:backup|4.4 Backup]] | Backup-Verschlüsselung | ---- << [[.:key_encapsulation|← 7.2 Key Encapsulation]] | [[.:start|↑ Verschlüsselung-Übersicht]] | [[de:int:pqcrypt:szenarien:start|→ Alle Szenarien]] >> {{tag>szenario verschluesselung datei aes-gcm argon2id}} ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//