====== KeyDerivationExtensions ====== **Namespace:** ''WvdS.System.Security.Cryptography.KeyDerivation'' Statični razred za izpeljavo ključev (Key Derivation Functions) s podporo za post-kvantno kriptografijo. Podpira HKDF, PBKDF2 in Argon2id. ===== Pregled ===== Podprti KDF-algoritmi: ^ KDF ^ Standard ^ Uporaba ^ | HKDF | RFC 5869 | Sejni ključi iz skupnih skrivnosti | | PBKDF2 | RFC 8018 | Ključi iz gesel | | Argon2id | RFC 9106 | Memory-hard KDF (gesla) | ===== HKDF - Izpeljava ključev na osnovi zgostitve ===== ==== DeriveKey ==== Izpelje ključe iz skupne skrivnosti (HKDF-Extract-then-Expand). // ML-KEM skupna skrivnost iz izmenjave ključev byte[] sharedSecret = session.SharedSecret; // Standardna izpeljava (SHA-256) byte[] aesKey = KeyDerivationExtensions.DeriveKey( sharedSecret, outputLength: 32); // 256 bitov // S soljo in kontekstnimi informacijami byte[] salt = RandomNumberGenerator.GetBytes(32); byte[] info = Encoding.UTF8.GetBytes("MyApp-Session-Key"); byte[] sessionKey = KeyDerivationExtensions.DeriveKey( sharedSecret, outputLength: 32, salt: salt, info: info, hashAlgorithm: HashAlgorithmName.SHA384); // Opcijsko ==== HkdfExtract ==== Ekstrahira PRK (Pseudorandom Key) iz vhodnega materiala ključa. byte[] inputKeyMaterial = GetSharedSecret(); byte[] salt = RandomNumberGenerator.GetBytes(32); byte[] prk = KeyDerivationExtensions.HkdfExtract( inputKeyMaterial, salt: salt, hashAlgorithm: HashAlgorithmName.SHA256); // PRK ima enako dolžino kot izhod zgoščevalne funkcije (32 bajtov pri SHA-256) ==== HkdfExpand ==== Razširi PRK v izhodni material ključa. byte[] prk = GetPrk(); // Šifrirni ključ byte[] encKey = KeyDerivationExtensions.HkdfExpand( prk, outputLength: 32, info: Encoding.UTF8.GetBytes("encryption")); // MAC ključ byte[] macKey = KeyDerivationExtensions.HkdfExpand( prk, outputLength: 32, info: Encoding.UTF8.GetBytes("mac")); ===== Hibridna izpeljava ključev ===== Kombinira klasične (ECDH/DH) in PQ (ML-KEM) skupne skrivnosti. ==== DeriveHybridKey ==== byte[] ecdhSecret = GetEcdhSharedSecret(); byte[] mlKemSecret = GetMlKemSharedSecret(); // Hibridni način: Obe skrivnosti sta kombinirani byte[] hybridKey = KeyDerivationExtensions.DeriveHybridKey( classicSecret: ecdhSecret, pqSecret: mlKemSecret, outputLength: 32, mode: CryptoMode.Hybrid); // Samo klasično byte[] classicKey = KeyDerivationExtensions.DeriveHybridKey( classicSecret: ecdhSecret, pqSecret: null, outputLength: 32, mode: CryptoMode.Classic); // Samo post-kvantno byte[] pqKey = KeyDerivationExtensions.DeriveHybridKey( classicSecret: null, pqSecret: mlKemSecret, outputLength: 32, mode: CryptoMode.PostQuantum); // Lastne informacije byte[] customKey = KeyDerivationExtensions.DeriveHybridKey( classicSecret: ecdhSecret, pqSecret: mlKemSecret, outputLength: 64, mode: CryptoMode.Hybrid, info: Encoding.UTF8.GetBytes("MyProtocol-v1")); **Kombinacija ključev:** Hybrid Mode: IKM = classicSecret || pqSecret Key = HKDF-SHA256(IKM, info="WvdS-Hybrid-Key") ==== DeriveHybridKeyMaterial ==== Izpelje več ključev za različne namene. using HybridKeyMaterial keyMaterial = KeyDerivationExtensions.DeriveHybridKeyMaterial( classicSecret: ecdhSecret, pqSecret: mlKemSecret, mode: CryptoMode.Hybrid); // Uporaba byte[] encKey = keyMaterial.EncryptionKey; // 32 bajtov byte[] macKey = keyMaterial.MacKey; // 32 bajtov byte[] iv = keyMaterial.Iv; // 16 bajtov byte[] authKey = keyMaterial.AuthKey; // 32 bajtov // IDisposable: Ključi so varno izbrisani ===== PBKDF2 - Izpeljava ključev iz gesel ===== ==== Pbkdf2 ==== string password = "SecurePassword123!"; byte[] salt = RandomNumberGenerator.GetBytes(32); // Standardni PBKDF2 byte[] key = KeyDerivationExtensions.Pbkdf2( password, salt, iterations: 100000, outputLength: 32); // S PQ-entropijo (dodatna zaščita) byte[] pqEntropy = GetPqEntropy(); byte[] enhancedKey = KeyDerivationExtensions.Pbkdf2( password, salt, iterations: 100000, outputLength: 32, pqEntropy: pqEntropy, // Kombinirana s soljo hashAlgorithm: HashAlgorithmName.SHA512); ==== Pbkdf2WithPqSalt ==== PBKDF2 s PQ-okrepljeno soljo (javni ključ je vključen v izračun soli). string password = "UserPassword"; byte[] baseSalt = RandomNumberGenerator.GetBytes(16); byte[] mlKemPublicKey = GetRecipientPublicKey(); // Salt = SHA256(baseSalt || pqPublicKey) byte[] key = KeyDerivationExtensions.Pbkdf2WithPqSalt( password, baseSalt, mlKemPublicKey, iterations: 100000, outputLength: 32); **Prednost:** Tudi pri enakem geslu in osnovni soli se za vsakega prejemnika (različen PQ javni ključ) izpelje drugačen ključ. ===== Argon2id - Memory-Hard KDF ===== Argon2id preko OpenSSL 3.6 - odporen proti GPU/ASIC napadom. ==== Argon2id (polje bajtov) ==== byte[] password = Encoding.UTF8.GetBytes("SecurePassword"); byte[] salt = RandomNumberGenerator.GetBytes(16); // Najmanj 16 bajtov byte[] key = KeyDerivationExtensions.Argon2id( password, salt, outputLength: 32, // Dolžina ključa iterations: 3, // Časovni stroški (t) memoryKiB: 65536, // Pomnilnik: 64 MB parallelism: 4); // Niti (p) ==== Argon2id (niz) ==== string password = "UserPassword123"; byte[] salt = RandomNumberGenerator.GetBytes(16); byte[] key = KeyDerivationExtensions.Argon2id( password, salt, outputLength: 32, iterations: 3, memoryKiB: 65536, parallelism: 4); **Priporočeni parametri:** ^ Aplikacija ^ Iteracije (t) ^ Pomnilnik (m) ^ Paralelizem (p) ^ | Zgoščevanje gesel | 3 | 64 MB | 4 | | Visoka varnost | 4 | 256 MB | 4 | | Nizek pomnilnik | 4 | 16 MB | 4 | ===== TLS izpeljava ključev ===== ==== DeriveTlsKeys (TLS 1.2 stil) ==== byte[] preMasterSecret = GetPreMasterSecret(); byte[] clientRandom = GetClientRandom(); byte[] serverRandom = GetServerRandom(); using TlsKeyMaterial keys = KeyDerivationExtensions.DeriveTlsKeys( preMasterSecret, clientRandom, serverRandom, mode: CryptoMode.Hybrid); // Uporaba var clientKey = keys.ClientWriteKey; // 32 bajtov var serverKey = keys.ServerWriteKey; // 32 bajtov var clientIv = keys.ClientWriteIv; // 12 bajtov var serverIv = keys.ServerWriteIv; // 12 bajtov ==== DeriveTls13Keys ==== TLS 1.3 kompatibilen razpored ključev. byte[]? pskSecret = null; // Pre-Shared Key (opcijsko) byte[] ecdhSecret = GetEcdhSecret(); byte[] pqSecret = GetMlKemSecret(); byte[] clientHello = GetClientHelloBytes(); byte[] serverHello = GetServerHelloBytes(); using Tls13KeySchedule schedule = KeyDerivationExtensions.DeriveTls13Keys( pskSecret, ecdhSecret, pqSecret, clientHello, serverHello, mode: CryptoMode.Hybrid); // Handshake Traffic Secrets var clientHsSecret = schedule.ClientHandshakeTrafficSecret; var serverHsSecret = schedule.ServerHandshakeTrafficSecret; // Application Traffic Secrets var clientAppSecret = schedule.ClientApplicationTrafficSecret; var serverAppSecret = schedule.ServerApplicationTrafficSecret; // Resumption Secret var resumptionSecret = schedule.ResumptionMasterSecret; ===== Podatkovni razredi ===== ==== HybridKeyMaterial ==== Vsebnik za izpeljane ključe z varnim čiščenjem pomnilnika. ^ Lastnost ^ Tip ^ Dolžina ^ Opis ^ | ''EncryptionKey'' | byte[] | 32 | AES-ključ | | ''MacKey'' | byte[] | 32 | HMAC-ključ | | ''Iv'' | byte[] | 16 | Inicializacijski vektor | | ''AuthKey'' | byte[] | 32 | Overitveni ključ | using HybridKeyMaterial keys = DeriveKeys(); // Ključi so pri Dispose() varno izbrisani // (CryptographicOperations.ZeroMemory) ==== TlsKeyMaterial ==== TLS 1.2 stil materiala ključev. ^ Lastnost ^ Tip ^ Opis ^ | ''MasterSecret'' | byte[] | 48 bajtov Master Secret | | ''ClientWriteKey'' | byte[] | Šifrirni ključ na strani odjemalca | | ''ServerWriteKey'' | byte[] | Šifrirni ključ na strani strežnika | | ''ClientWriteIv'' | byte[] | IV na strani odjemalca | | ''ServerWriteIv'' | byte[] | IV na strani strežnika | | ''ClientWriteMacKey'' | byte[] | MAC ključ odjemalca (prazen pri GCM) | | ''ServerWriteMacKey'' | byte[] | MAC ključ strežnika (prazen pri GCM) | ==== Tls13KeySchedule ==== TLS 1.3 razpored ključev. ^ Lastnost ^ Tip ^ Opis ^ | ''ClientHandshakeTrafficSecret'' | byte[]? | Client Handshake Traffic Secret | | ''ServerHandshakeTrafficSecret'' | byte[]? | Server Handshake Traffic Secret | | ''ClientApplicationTrafficSecret'' | byte[]? | Client Application Traffic Secret | | ''ServerApplicationTrafficSecret'' | byte[]? | Server Application Traffic Secret | | ''ResumptionMasterSecret'' | byte[]? | Session Resumption Secret | ===== Pregled metod ===== ==== HKDF ==== ^ Metoda ^ Parametri ^ Vrnjeno ^ | ''DeriveKey'' | byte[] sharedSecret, int outputLength, byte[]? salt, byte[]? info, HashAlgorithmName? | byte[] | | ''HkdfExtract'' | byte[] ikm, byte[]? salt, HashAlgorithmName? | byte[] | | ''HkdfExpand'' | byte[] prk, int outputLength, byte[]? info, HashAlgorithmName? | byte[] | ==== Hibridno ==== ^ Metoda ^ Parametri ^ Vrnjeno ^ | ''DeriveHybridKey'' | byte[]? classicSecret, byte[]? pqSecret, int outputLength, CryptoMode, byte[]? info | byte[] | | ''DeriveHybridKeyMaterial'' | byte[]? classicSecret, byte[]? pqSecret, CryptoMode | HybridKeyMaterial | ==== PBKDF2 ==== ^ Metoda ^ Parametri ^ Vrnjeno ^ | ''Pbkdf2'' | string password, byte[] salt, int iterations, int outputLength, byte[]? pqEntropy, HashAlgorithmName? | byte[] | | ''Pbkdf2WithPqSalt'' | string password, byte[] baseSalt, byte[] pqPublicKey, int iterations, int outputLength | byte[] | ==== Argon2id ==== ^ Metoda ^ Parametri ^ Vrnjeno ^ | ''Argon2id'' | byte[] password, byte[] salt, int outputLength, int iterations, int memoryKiB, int parallelism | byte[] | | ''Argon2id'' | string password, byte[] salt, int outputLength, int iterations, int memoryKiB, int parallelism | byte[] | ==== TLS ==== ^ Metoda ^ Parametri ^ Vrnjeno ^ | ''DeriveTlsKeys'' | byte[] preMasterSecret, byte[] clientRandom, byte[] serverRandom, CryptoMode | TlsKeyMaterial | | ''DeriveTls13Keys'' | byte[]? psk, byte[]? ecdh, byte[]? pq, byte[] clientHello, byte[] serverHello, CryptoMode | Tls13KeySchedule | ===== Popoln primer ===== using WvdS.System.Security.Cryptography; using WvdS.System.Security.Cryptography.KeyDerivation; using WvdS.System.Security.Cryptography.KeyExchange; // 1. Izvedba izmenjave ključev using var session = new KeyExchangeService(); await session.InitiateKeyExchangeAsync(recipientPublicKey, CryptoMode.Hybrid); // 2. Izpeljava hibridnega materiala ključev using HybridKeyMaterial keys = KeyDerivationExtensions.DeriveHybridKeyMaterial( classicSecret: session.ClassicSharedSecret, pqSecret: session.PqSharedSecret, mode: CryptoMode.Hybrid); // 3. Uporaba ključev using var aes = Aes.Create(); aes.Key = keys.EncryptionKey; using var hmac = new HMACSHA256(keys.MacKey); // 4. Izvedba šifriranja // ... // 5. Ključi so samodejno varno izbrisani ===== Varnostni nasveti ===== * Vsi ''IDisposable'' razredi implementirajo ''CryptographicOperations.ZeroMemory'' * Argon2id potrebuje OpenSSL 3.6 (ni na voljo v .NET BCL) * PBKDF2 z manj kot 100.000 iteracijami ni priporočljiv * Sol mora biti pri PBKDF2/Argon2id vedno naključna in dovolj dolga (min. 16 bajtov) **Varnost hibridnega načina:** V hibridnem načinu je končni ključ kompromitiran le, če sta ZLOMLJENI OBE skrivnosti (klasična IN PQ). To zagotavlja zaščito tako pred klasičnimi kot pred kvantnimi napadi. ===== Glej tudi ===== * [[.:start|KeyDerivation Namespace]] * [[.:hybridkeymaterial|HybridKeyMaterial]] * [[.:tlskeymaterial|TlsKeyMaterial]] * [[.:tls13keyschedule|Tls13KeySchedule]] * [[..:keyexchange:start|KeyExchange Namespace]] * [[..:encryption:start|Encryption Namespace]] * [[sl:int:pqcrypt:konzepte:algorithmen:ml-kem|Algoritem ML-KEM]] ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//