~~NOTOC~~
====== Scenario 11.1: Generazione chiavi ======
**Categoria:** [[.:start|Gestione chiavi]] \\
**Complessità:** Media \\
**Prerequisiti:** OpenSSL 3.6+, fonte di entropia sicura \\
**Tempo stimato:** 15-20 minuti
----
===== Descrizione =====
Questo scenario descrive la **generazione sicura di chiavi crittografiche** per algoritmi Post-Quantum. La generazione delle chiavi è il passo più critico - chiavi deboli compromettono tutte le operazioni basate su di esse.
**Algoritmi supportati:**
^ Algoritmo ^ Tipo ^ Sicurezza ^ Dimensione chiave (Public) ^
| **ML-DSA-44** | Firma | 128-bit | 1.312 Bytes |
| **ML-DSA-65** | Firma | 192-bit | 1.952 Bytes |
| **ML-DSA-87** | Firma | 256-bit | 2.592 Bytes |
| **ML-KEM-512** | KEM | 128-bit | 800 Bytes |
| **ML-KEM-768** | KEM | 192-bit | 1.184 Bytes |
| **ML-KEM-1024** | KEM | 256-bit | 1.568 Bytes |
----
===== Workflow =====
flowchart LR
ENTROPY[Fonte entropia] --> RNG[CSPRNG]
RNG --> KEYGEN[Generazione chiave]
PARAM[Scegliere parametri] --> KEYGEN
KEYGEN --> PUBKEY[Chiave pubblica]
KEYGEN --> PRIVKEY[Chiave privata]
PRIVKEY --> ENCRYPT[Salvare crittografata]
style ENTROPY fill:#fff3e0
style ENCRYPT fill:#e8f5e9
----
===== Esempio codice: Chiave firma ML-DSA =====
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using var ctx = PqCryptoContext.Initialize();
// Generare coppia chiavi ML-DSA-65 (consigliato)
using var signatureKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65);
Console.WriteLine("Chiave ML-DSA-65 generata:");
Console.WriteLine($" Chiave pubblica: {signatureKey.PublicKey.GetRawData().Length} Bytes");
Console.WriteLine($" OID: {signatureKey.PublicKey.Oid.Value}");
// Salvare come PEM
signatureKey.PublicKey.ToPemFile("signing.pub.pem");
signatureKey.ToEncryptedPemFile("signing.key.pem", "SecurePassword123!");
// Diversi livelli di sicurezza
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 (Alta sicurezza)
----
===== Esempio codice: Chiave crittografia ML-KEM =====
using var ctx = PqCryptoContext.Initialize();
// ML-KEM-768 per Key Encapsulation (consigliato)
using var kemKey = ctx.GenerateKeyPair(PqAlgorithm.MlKem768);
Console.WriteLine("Chiave ML-KEM-768 generata:");
Console.WriteLine($" Chiave pubblica: {kemKey.PublicKey.GetRawData().Length} Bytes");
Console.WriteLine($" Utilizzo: Key Encapsulation");
// Salvare
kemKey.PublicKey.ToPemFile("encryption.pub.pem");
kemKey.ToEncryptedPemFile("encryption.key.pem", "EncryptionPassword!");
----
===== Esempio codice: Coppia chiavi ibride =====
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();
// Chiave classica
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("Algoritmo sconosciuto")
};
// Chiave PQ
var pqKey = ctx.GenerateKeyPair(pq);
return new HybridKeyPair
{
ClassicalKey = classicalKey,
PqKey = pqKey
};
}
public void SaveToFiles(string baseName, string password)
{
// Chiave classica
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);
}
// Chiave PQ
PqKey.ToEncryptedPemFile($"{baseName}-pq.key.pem", password);
PqKey.PublicKey.ToPemFile($"{baseName}-pq.pub.pem");
}
}
public enum ClassicalAlgorithm
{
RsA4096,
EcdsaP384,
EcdhP384
}
----
===== Generazione batch =====
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($"Generata: {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
);
}
}
}
----
===== Entropia e numeri casuali =====
public class EntropySource
{
// Sistema CSPRNG (consigliato)
public static byte[] GetSystemEntropy(int bytes)
{
return RandomNumberGenerator.GetBytes(bytes);
}
// Verificare Hardware RNG
public static bool IsHardwareRngAvailable()
{
try
{
// Intel RDRAND
return System.Runtime.Intrinsics.X86.Rdrand.IsSupported;
}
catch
{
return false;
}
}
// Miscelare entropia aggiuntiva (opzionale)
public static byte[] EnhancedEntropy(int bytes)
{
var systemEntropy = RandomNumberGenerator.GetBytes(bytes);
// Miscelare altre fonti di entropia
var timestamp = BitConverter.GetBytes(DateTime.UtcNow.Ticks);
var processId = BitConverter.GetBytes(Environment.ProcessId);
var gcMemory = BitConverter.GetBytes(GC.GetTotalMemory(false));
// Combinare con hash
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);
// Entropia estesa per ulteriori bytes
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;
}
}
----
===== Requisiti specifici per settore =====
^ Settore ^ Sicurezza min. ^ Algoritmo consigliato ^ HSM obbligatorio? ^
| **IT Standard** | 128-bit | ML-DSA-65 / ML-KEM-768 | No |
| **Finanza** | 192-bit | ML-DSA-65 / ML-KEM-768 | Sì |
| **Sanità** | 192-bit | ML-DSA-65 / ML-KEM-768 | Consigliato |
| **Governo** | 256-bit | ML-DSA-87 / ML-KEM-1024 | Sì |
| **IoT** | 128-bit | ML-DSA-44 / ML-KEM-512 | No |
----
===== Scenari correlati =====
^ Relazione ^ Scenario ^ Descrizione ^
| **Passo successivo** | [[.:speicherung|11.2 Archiviazione chiavi]] | Archiviazione sicura |
| **Correlato** | [[.:rotation|11.3 Rotazione chiavi]] | Scambio regolare |
| **Correlato** | [[it:int:pqcrypt:szenarien:csr:csr_server|2.1 CSR Server]] | Creare CSR |
----
<< [[.:start|Panoramica chiavi]] | [[it:int:pqcrypt:szenarien:start|Scenari]] | [[.:speicherung|11.2 Archiviazione chiavi]] >>
{{tag>scenario chiave generazione ml-dsa ml-kem entropia}}
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//