Scenarij 11.1: Generiranje ključeva

Kategorija: 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<string, PqKeyPair> GenerateBatch(
        int count,
        PqAlgorithm algorithm,
        string namePrefix)
    {
        using var ctx = PqCryptoContext.Initialize();
        var keys = new Dictionary<string, PqKeyPair>();
 
        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<string, PqKeyPair> 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 11.2 Pohrana ključeva Sigurno spremanje
Povezano 11.3 Rotacija ključeva Redovita zamjena
Povezano 2.1 Serverski CSR Kreiranje CSR-a

« ← Pregled ključeva | ↑ Scenariji | 11.2 Pohrana ključeva → »


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional

Zuletzt geändert: 30.01.2026. u 00:28