~~NOTOC~~
====== Scenarij 7.3: Šifriranje datoteka ======
**Kategorija:** [[.:start|Šifriranje]] \\
**Složenost:** ⭐⭐⭐ (Srednja) \\
**Preduvjeti:** Ključni materijal ili lozinka \\
**Procijenjeno vrijeme:** 15-20 minuta
----
===== Opis =====
Ovaj scenarij opisuje **sigurno šifriranje datoteka** post-kvantno sigurnim postupcima. Implementacija podržava šifriranje temeljeno na lozinci i šifriranje temeljeno na ključevima.
**Slučajevi korištenja:**
* Šifriranje sigurnosnih kopija
* Zaštita dokumenata
* Konfiguracijske datoteke
* Arhiviranje
----
===== Tijek rada =====
flowchart TD
FILE[Originalna datoteka] --> COMPRESS[Opcionalno: komprimiranje]
COMPRESS --> CHUNK[Podjela na dijelove]
CHUNK --> ENCRYPT[AES-256-GCM po dijelu]
subgraph Derivacija ključa
PWD[Lozinka] --> KDF[Argon2id]
KDF --> KEY[Ključ za šifriranje]
end
KEY --> ENCRYPT
ENCRYPT --> OUTPUT[Šifrirana datoteka]
style KEY fill:#e8f5e9
style OUTPUT fill:#e3f2fd
----
===== Primjer koda: Šifriranje datoteke =====
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using System.Security.Cryptography;
using var ctx = PqCryptoContext.Initialize();
// Izvorna datoteka
string inputFile = "document.pdf";
string outputFile = "document.pdf.enc";
string password = "MySecurePassword123!";
// Parametri šifriranja
var salt = RandomNumberGenerator.GetBytes(32);
var nonce = RandomNumberGenerator.GetBytes(12);
// Derivacija ključa iz lozinke (Argon2id)
var key = ctx.DeriveKeyArgon2id(
password: Encoding.UTF8.GetBytes(password),
salt: salt,
outputLength: 32,
iterations: 3,
memoryKiB: 65536, // 64 MB
parallelism: 4
);
// Čitanje datoteke
var plaintext = File.ReadAllBytes(inputFile);
// Šifriranje s 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);
// Zapisivanje zaglavlja + ciphertexta
using var output = File.Create(outputFile);
using var writer = new BinaryWriter(output);
// Magic number
writer.Write(Encoding.ASCII.GetBytes("PQENC"));
// Verzija
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($"Datoteka šifrirana: {outputFile}");
Console.WriteLine($" Original: {plaintext.Length:N0} bajtova");
Console.WriteLine($" Šifrirano: {output.Length:N0} bajtova");
----
===== Primjer koda: Dešifriranje datoteke =====
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);
// Provjera magic numbera
var magic = Encoding.ASCII.GetString(reader.ReadBytes(5));
if (magic != "PQENC")
throw new InvalidDataException("Nevaljani format datoteke");
// Provjera verzije
var version = reader.ReadByte();
if (version != 1)
throw new NotSupportedException($"Verzija {version} nije podržana");
// Čitanje parametara
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);
// Derivacija ključa (isti parametri!)
var key = ctx.DeriveKeyArgon2id(
password: Encoding.UTF8.GetBytes(password),
salt: salt,
outputLength: 32,
iterations: 3,
memoryKiB: 65536,
parallelism: 4
);
// Dešifriranje
var plaintext = new byte[ciphertext.Length];
using var aes = new OpenSslAesGcm(key);
aes.Decrypt(nonce, ciphertext, tag, plaintext);
// Spremanje
File.WriteAllBytes(outputFile, plaintext);
Console.WriteLine($"Datoteka dešifrirana: {outputFile}");
----
===== Streaming za velike datoteke =====
public class FileEncryptor
{
private const int ChunkSize = 64 * 1024; // 64 KB dijelovi
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);
// Zapisivanje zaglavlja
writer.Write(Encoding.ASCII.GetBytes("PQENC"));
writer.Write((byte)2); // Verzija 2 = Streaming
// Broj dijelova
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();
// Jedinstveni nonce po dijelu (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 za zaštitu redoslijeda
var aad = BitConverter.GetBytes(chunkIndex);
aes.Encrypt(nonce, chunk, ciphertext, tag, aad);
// Zapisivanje dijela
writer.Write(nonce);
writer.Write(tag);
writer.Write(ciphertext.Length);
writer.Write(ciphertext);
chunkIndex++;
}
Console.WriteLine($"Šifrirano: {chunkIndex} dijelova");
}
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);
// Čitanje zaglavlja
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);
}
}
}
----
===== Hibridno šifriranje s ML-KEM =====
public class HybridFileEncryptor
{
public void EncryptForRecipient(
string inputPath,
string outputPath,
byte[] recipientMlKemPublicKey)
{
using var ctx = PqCryptoContext.Initialize();
// ML-KEM enkapsulacija ključa
var pubKey = ctx.ImportPublicKey(recipientMlKemPublicKey);
var (kemCiphertext, sharedSecret) = ctx.Encapsulate(pubKey);
// Derivacija ključa za šifriranje datoteke
var fileKey = ctx.DeriveKey(
sharedSecret,
outputLength: 32,
info: Encoding.UTF8.GetBytes("file-encryption-key")
);
// Šifriranje datoteke
var encryptor = new FileEncryptor();
var tempFile = Path.GetTempFileName();
encryptor.EncryptLargeFile(inputPath, tempFile, fileKey);
// Output s KEM Ciphertextom
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);
// Dodavanje šifriranog sadržaja
using var encryptedContent = File.OpenRead(tempFile);
encryptedContent.CopyTo(output);
File.Delete(tempFile);
}
}
----
===== Specifikacija formata datoteke =====
PQENC v1 (Single-Shot):
┌─────────────────────────────────┐
│ Magic: "PQENC" (5 bajtova) │
│ Version: 0x01 (1 bajt) │
│ Salt Length (4 bajta) │
│ Salt (varijabilno) │
│ Nonce Length (4 bajta) │
│ Nonce (12 bajtova) │
│ Tag Length (4 bajta) │
│ Tag (16 bajtova) │
│ Ciphertext Length (4 bajta) │
│ Ciphertext (varijabilno) │
└─────────────────────────────────┘
PQENC v2 (Streaming):
┌─────────────────────────────────┐
│ Magic: "PQENC" (5 bajtova) │
│ Version: 0x02 (1 bajt) │
│ Total Chunks (4 bajta) │
├─────────────────────────────────┤
│ Chunk 0: │
│ Nonce (12 bajtova) │
│ Tag (16 bajtova) │
│ Ciphertext Length (4 bajta) │
│ Ciphertext (varijabilno) │
├─────────────────────────────────┤
│ Chunk 1: ... │
└─────────────────────────────────┘
----
===== Povezani scenariji =====
^ Odnos ^ Scenarij ^ Opis ^
| **Komponenta** | [[.:key_encapsulation|7.2 Enkapsulacija ključa]] | ML-KEM za primatelja |
| **Povezano** | [[.:hybrid_encryption|7.1 Hibridno šifriranje]] | Hibridni koncept |
| **Povezano** | [[hr:int:pqcrypt:szenarien:verwaltung:backup|4.4 Sigurnosna kopija]] | Šifriranje kopija |
----
<< [[.:key_encapsulation|← 7.2 Enkapsulacija ključa]] | [[.:start|↑ Pregled šifriranja]] | [[hr:int:pqcrypt:szenarien:start|→ Svi scenariji]] >>
{{tag>scenarij šifriranje datoteka aes-gcm argon2id}}
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//