~~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//