~~NOTOC~~ ====== Scenarij 11.1: Generiranje ključeva ====== **Kategorija:** [[.:start|Upravljanje ključevima]] \\ **Složenost:** ⭐⭐⭐ (Srednja) \\ **Preduvjeti:** OpenSSL 3.6+, siguran izvor entropije \\ **Procijenjeno vrijeme:** 15-20 minuta ---- ===== Opis ===== Ovaj scenarij opisuje **sigurno generiranje kriptografskih ključeva** za Post-Quantum algoritme. Generiranje ključeva je najkritičniji korak - slabi ključevi ugrožavaju sve operacije koje se na njima temelje. **Podržani algoritmi:** ^ Algoritam ^ Tip ^ Sigurnost ^ Veličina ključa (Javni) ^ | **ML-DSA-44** | Potpis | 128-bit | 1.312 bajta | | **ML-DSA-65** | Potpis | 192-bit | 1.952 bajta | | **ML-DSA-87** | Potpis | 256-bit | 2.592 bajta | | **ML-KEM-512** | KEM | 128-bit | 800 bajta | | **ML-KEM-768** | KEM | 192-bit | 1.184 bajta | | **ML-KEM-1024** | KEM | 256-bit | 1.568 bajta | ---- ===== Tijek rada ===== flowchart LR ENTROPY[Izvor entropije] --> RNG[CSPRNG] RNG --> KEYGEN[Generiranje ključa] PARAM[Odabir parametara] --> KEYGEN KEYGEN --> PUBKEY[Javni ključ] KEYGEN --> PRIVKEY[Privatni ključ] PRIVKEY --> ENCRYPT[Šifrirano spremanje] style ENTROPY fill:#fff3e0 style ENCRYPT fill:#e8f5e9 ---- ===== Primjer koda: ML-DSA ključ za potpis ===== using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using var ctx = PqCryptoContext.Initialize(); // Generiranje ML-DSA-65 para ključeva (preporučeno) using var signatureKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65); Console.WriteLine("ML-DSA-65 ključ generiran:"); Console.WriteLine($" Javni ključ: {signatureKey.PublicKey.GetRawData().Length} bajta"); Console.WriteLine($" OID: {signatureKey.PublicKey.Oid.Value}"); // Spremanje kao PEM signatureKey.PublicKey.ToPemFile("signing.pub.pem"); signatureKey.ToEncryptedPemFile("signing.key.pem", "SecurePassword123!"); // Različite razine sigurnosti using var mlDsa44 = ctx.GenerateKeyPair(PqAlgorithm.MlDsa44); // 128-bit using var mlDsa65 = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65); // 192-bit (Standard) using var mlDsa87 = ctx.GenerateKeyPair(PqAlgorithm.MlDsa87); // 256-bit (Visoka sigurnost) ---- ===== Primjer koda: ML-KEM ključ za šifriranje ===== using var ctx = PqCryptoContext.Initialize(); // ML-KEM-768 za Key Encapsulation (preporučeno) using var kemKey = ctx.GenerateKeyPair(PqAlgorithm.MlKem768); Console.WriteLine("ML-KEM-768 ključ generiran:"); Console.WriteLine($" Javni ključ: {kemKey.PublicKey.GetRawData().Length} bajta"); Console.WriteLine($" Uporaba: Key Encapsulation"); // Spremanje kemKey.PublicKey.ToPemFile("encryption.pub.pem"); kemKey.ToEncryptedPemFile("encryption.key.pem", "EncryptionPassword!"); ---- ===== Primjer koda: Hibridni par ključeva ===== public class HybridKeyPair { public AsymmetricAlgorithm ClassicalKey { get; set; } public PqKeyPair PqKey { get; set; } public static HybridKeyPair Generate( ClassicalAlgorithm classical, PqAlgorithm pq) { using var ctx = PqCryptoContext.Initialize(); // Klasični ključ var classicalKey = classical switch { ClassicalAlgorithm.RsA4096 => RSA.Create(4096), ClassicalAlgorithm.EcdsaP384 => ECDsa.Create(ECCurve.NamedCurves.nistP384), ClassicalAlgorithm.EcdhP384 => ECDiffieHellman.Create(ECCurve.NamedCurves.nistP384), _ => throw new ArgumentException("Nepoznat algoritam") }; // PQ ključ var pqKey = ctx.GenerateKeyPair(pq); return new HybridKeyPair { ClassicalKey = classicalKey, PqKey = pqKey }; } public void SaveToFiles(string baseName, string password) { // Klasični ključ if (ClassicalKey is RSA rsa) { var rsaPem = rsa.ExportRSAPrivateKeyPem(); File.WriteAllText($"{baseName}-classical.key.pem", rsaPem); } else if (ClassicalKey is ECDsa ecdsa) { var ecPem = ecdsa.ExportECPrivateKeyPem(); File.WriteAllText($"{baseName}-classical.key.pem", ecPem); } // PQ ključ PqKey.ToEncryptedPemFile($"{baseName}-pq.key.pem", password); PqKey.PublicKey.ToPemFile($"{baseName}-pq.pub.pem"); } } public enum ClassicalAlgorithm { RsA4096, EcdsaP384, EcdhP384 } ---- ===== Grupno generiranje ===== public class KeyGenerationService { public Dictionary GenerateBatch( int count, PqAlgorithm algorithm, string namePrefix) { using var ctx = PqCryptoContext.Initialize(); var keys = new Dictionary(); for (int i = 0; i < count; i++) { var name = $"{namePrefix}-{i:D4}"; var keyPair = ctx.GenerateKeyPair(algorithm); keys[name] = keyPair; Console.WriteLine($"Generirano: {name}"); } return keys; } public void SaveBatch( Dictionary keys, string outputDir, string password) { Directory.CreateDirectory(outputDir); foreach (var (name, key) in keys) { key.PublicKey.ToPemFile(Path.Combine(outputDir, $"{name}.pub.pem")); key.ToEncryptedPemFile( Path.Combine(outputDir, $"{name}.key.pem"), password ); } } } ---- ===== Entropija i nasumični brojevi ===== public class EntropySource { // Sustavni CSPRNG (preporučeno) public static byte[] GetSystemEntropy(int bytes) { return RandomNumberGenerator.GetBytes(bytes); } // Provjera hardverskog RNG-a public static bool IsHardwareRngAvailable() { try { // Intel RDRAND return System.Runtime.Intrinsics.X86.Rdrand.IsSupported; } catch { return false; } } // Dodatna entropija (opcionalno) public static byte[] EnhancedEntropy(int bytes) { var systemEntropy = RandomNumberGenerator.GetBytes(bytes); // Miješanje dodatnih izvora entropije var timestamp = BitConverter.GetBytes(DateTime.UtcNow.Ticks); var processId = BitConverter.GetBytes(Environment.ProcessId); var gcMemory = BitConverter.GetBytes(GC.GetTotalMemory(false)); // Kombiniranje hashom using var sha = SHA256.Create(); var combined = new byte[systemEntropy.Length + timestamp.Length + processId.Length + gcMemory.Length]; Buffer.BlockCopy(systemEntropy, 0, combined, 0, systemEntropy.Length); Buffer.BlockCopy(timestamp, 0, combined, systemEntropy.Length, timestamp.Length); Buffer.BlockCopy(processId, 0, combined, systemEntropy.Length + timestamp.Length, processId.Length); Buffer.BlockCopy(gcMemory, 0, combined, systemEntropy.Length + timestamp.Length + processId.Length, gcMemory.Length); var hashed = sha.ComputeHash(combined); // Proširena entropija za dodatne bajtove var result = new byte[bytes]; for (int i = 0; i < bytes; i += 32) { var blockSize = Math.Min(32, bytes - i); Buffer.BlockCopy(hashed, 0, result, i, blockSize); hashed = sha.ComputeHash(hashed); } return result; } } ---- ===== Zahtjevi specifični za industriju ===== ^ Industrija ^ Min. sigurnost ^ Preporučeni algoritam ^ HSM obavezan? ^ | **Standardni IT** | 128-bit | ML-DSA-65 / ML-KEM-768 | Ne | | **Financijski sektor** | 192-bit | ML-DSA-65 / ML-KEM-768 | Da | | **Zdravstvo** | 192-bit | ML-DSA-65 / ML-KEM-768 | Preporučeno | | **Vlada** | 256-bit | ML-DSA-87 / ML-KEM-1024 | Da | | **IoT** | 128-bit | ML-DSA-44 / ML-KEM-512 | Ne | ---- ===== Povezani scenariji ===== ^ Povezanost ^ Scenarij ^ Opis ^ | **Sljedeći korak** | [[.:speicherung|11.2 Pohrana ključeva]] | Sigurno spremanje | | **Povezano** | [[.:rotation|11.3 Rotacija ključeva]] | Redovita zamjena | | **Povezano** | [[hr:int:pqcrypt:szenarien:csr:csr_server|2.1 Serverski CSR]] | Kreiranje CSR-a | ---- << [[.:start|← Pregled ključeva]] | [[hr:int:pqcrypt:szenarien:start|↑ Scenariji]] | [[.:speicherung|11.2 Pohrana ključeva →]] >> {{tag>scenarij ključ generiranje ml-dsa ml-kem entropija}} ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//