====== WasmCryptoProvider ====== **Namespace:** ''WvdS.System.Security.Cryptography.Providers'' JavaScript Interop-bazirani kripto-provider za Blazor WebAssembly. Komunicira putem ''IJSRuntime'' s ''openssl.wasm''. ===== Pregled ===== ''WasmCryptoProvider'' omogućuje Post-Quantum kriptografiju u Blazor WebAssembly aplikacijama putem: * JavaScript Interop prema WebAssembly-kompiliranom OpenSSL-u * Potpuno asinkronog API-ja (potrebno za JS Interop) * Identične funkcionalnosti kao ''NativeCryptoProvider'' ===== Arhitektura ===== Blazor WebAssembly │ ▼ ┌─────────────────┐ │ WasmCrypto- │ │ Provider │ │ (C#) │ └────────┬────────┘ │ IJSRuntime.InvokeAsync ▼ ┌─────────────────┐ │ wvds-crypto.js │ │ (JavaScript) │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ openssl.wasm │ │ (WebAssembly) │ └─────────────────┘ ===== Svojstva ===== ^ Svojstvo ^ Tip ^ Opis ^ | ''Name'' | string | ''%%"WASM (JS Interop)"%%'' | | ''IsAvailable'' | bool | ''true'' kada je inicijaliziran | ===== Dependency Injection ===== // Program.cs (Blazor WebAssembly) builder.Services.AddScoped(sp => new WasmCryptoProvider(sp.GetRequiredService())); ===== Inicijalizacija ===== @inject ICryptoProvider CryptoProvider @code { protected override async Task OnInitializedAsync() { await CryptoProvider.InitializeAsync(); if (CryptoProvider.IsAvailable) { var version = CryptoProvider.GetOpenSslVersion(); Console.WriteLine($"OpenSSL WASM: {version}"); } } } ===== Potrebne JS/WASM datoteke ===== U ''wwwroot/index.html'': ===== ML-DSA Operacije ===== ==== GenerateMlDsaKeyPairAsync ==== var (publicKey, privateKey) = await provider.GenerateMlDsaKeyPairAsync("ML-DSA-65"); ==== SignMlDsaAsync ==== byte[] data = Encoding.UTF8.GetBytes("Podaci potpisani u pregledniku"); byte[] signature = await provider.SignMlDsaAsync(data, privateKey); ==== VerifyMlDsaAsync ==== bool isValid = await provider.VerifyMlDsaAsync(data, signature, publicKey); ===== ML-KEM Operacije ===== ==== GenerateMlKemKeyPairAsync ==== var (publicKey, privateKey) = await provider.GenerateMlKemKeyPairAsync("ML-KEM-768"); ==== EncapsulateAsync ==== var (sharedSecret, ciphertext) = await provider.EncapsulateAsync(recipientPublicKey); ==== DecapsulateAsync ==== byte[] sharedSecret = await provider.DecapsulateAsync(ciphertext, privateKey); ===== Key Derivation Operacije ===== ==== Pbkdf2Async ==== PBKDF2 putem Web Crypto API-ja. byte[] salt = await provider.RandomBytesAsync(32); byte[] derivedKey = await provider.Pbkdf2Async( password: "UserPassword", salt: salt, iterations: 100000, outputLength: 32, hash: "SHA-256"); ==== Pbkdf2WithPqSaltAsync ==== PBKDF2 s PQ-pojačanom soli. byte[] key = await provider.Pbkdf2WithPqSaltAsync( password: "UserPassword", baseSalt: baseSalt, pqPublicKey: recipientPqPublicKey, iterations: 100000, outputLength: 32); ==== Argon2idAsync ==== Memory-hard KDF putem OpenSSL WASM. byte[] key = await provider.Argon2idAsync( password: passwordBytes, salt: salt, outputLength: 32, iterations: 3, memoryKiB: 65536, parallelism: 4); ===== Stream/Chunked šifriranje ===== ==== EncryptChunkedAsync / DecryptChunkedAsync ==== Za velike količine podataka s chunk obradom. byte[] key = await provider.RandomBytesAsync(32); // Šifriranje byte[] encrypted = await provider.EncryptChunkedAsync( plaintext, key, chunkSize: 65536); // 64 KB Chunks // Dešifriranje byte[] decrypted = await provider.DecryptChunkedAsync(encrypted, key); ==== EncryptStreamWithPqKeyAsync / DecryptStreamWithPqKeyAsync ==== Kombinira ML-KEM razmjenu ključeva s chunked šifriranjem. // Šifriranje za primatelja var (kemCiphertext, encryptedData) = await provider.EncryptStreamWithPqKeyAsync( plaintext, recipientPublicKey, chunkSize: 65536); // Dešifriranje byte[] decrypted = await provider.DecryptStreamWithPqKeyAsync( kemCiphertext, encryptedData, privateKey); ===== HKDF Operacije ===== ==== HkdfExtractAsync ==== byte[] prk = await provider.HkdfExtractAsync(salt, inputKeyMaterial); ==== HkdfExpandAsync ==== byte[] okm = await provider.HkdfExpandAsync(prk, info, outputLength: 32); ==== HkdfDeriveKeyAsync ==== Extract + Expand u jednom koraku. byte[] key = await provider.HkdfDeriveKeyAsync( ikm: sharedSecret, length: 32, salt: optionalSalt, info: contextInfo); ==== DeriveHybridKeyAsync ==== Kombinira klasičnu i PQ tajnu. byte[] hybridKey = await provider.DeriveHybridKeyAsync( classicSecret: ecdhSecret, pqSecret: mlKemSecret, outputLength: 32); ===== TLS 1.3 Key Derivation ===== ==== DeriveTls13KeysAsync ==== Tls13KeyMaterial keys = await provider.DeriveTls13KeysAsync( sharedSecret, clientHello, serverHello); // Pristup izvedenim tajnama var clientKey = keys.ClientHandshakeTrafficSecret; var serverKey = keys.ServerHandshakeTrafficSecret; ===== Hibridni potpisi ===== ==== CreateHybridSignatureAsync ==== Stvara hibridni potpis od klasičnog potpisa i ML-DSA. // Stvaranje klasičnog potpisa (npr. ECDSA) byte[] classicSig = CreateEcdsaSignature(data); // Stvaranje hibridnog potpisa byte[] hybridSig = await provider.CreateHybridSignatureAsync( data, classicSig, mlDsaPrivateKey); ===== Pomoćne metode ===== ==== RandomBytesAsync ==== Kriptografski sigurni nasumični brojevi putem Web Crypto API-ja. byte[] random = await provider.RandomBytesAsync(32); ===== Operacije s certifikatima ===== ==== CreateEphemeralCertificateAsync ==== byte[] certBytes = await provider.CreateEphemeralCertificateAsync( "CN=Browser Certificate", TimeSpan.FromHours(1), mlDsaPrivateKey); ==== SignCertificateAsync ==== byte[] signedCert = await provider.SignCertificateAsync(tbsCertificate, privateKey); ===== Pregled metoda ===== ==== ML-DSA ==== ^ Metoda ^ Parametri ^ Povratna vrijednost ^ | ''GenerateMlDsaKeyPairAsync'' | string algorithm | Task<(byte[], byte[])> | | ''SignMlDsaAsync'' | byte[] data, byte[] privateKey | Task | | ''VerifyMlDsaAsync'' | byte[] data, byte[] signature, byte[] publicKey | Task | ==== ML-KEM ==== ^ Metoda ^ Parametri ^ Povratna vrijednost ^ | ''GenerateMlKemKeyPairAsync'' | string algorithm | Task<(byte[], byte[])> | | ''EncapsulateAsync'' | byte[] publicKey | Task<(byte[], byte[])> | | ''DecapsulateAsync'' | byte[] ciphertext, byte[] privateKey | Task | ==== Key Derivation ==== ^ Metoda ^ Parametri ^ Povratna vrijednost ^ | ''Pbkdf2Async'' | string password, byte[] salt, int iterations, int outputLength, string hash | Task | | ''Pbkdf2WithPqSaltAsync'' | string password, byte[] baseSalt, byte[] pqPublicKey, int iterations, int outputLength | Task | | ''Argon2idAsync'' | byte[]/string password, byte[] salt, int outputLength, int iterations, int memoryKiB, int parallelism | Task | ==== HKDF ==== ^ Metoda ^ Parametri ^ Povratna vrijednost ^ | ''HkdfExtractAsync'' | byte[] salt, byte[] ikm | Task | | ''HkdfExpandAsync'' | byte[] prk, byte[] info, int length | Task | | ''HkdfDeriveKeyAsync'' | byte[] ikm, int length, byte[]? salt, byte[]? info | Task | | ''DeriveHybridKeyAsync'' | byte[] classicSecret, byte[] pqSecret, int outputLength | Task | ==== Šifriranje ==== ^ Metoda ^ Parametri ^ Povratna vrijednost ^ | ''EncryptChunkedAsync'' | byte[] plaintext, byte[] key, int chunkSize | Task | | ''DecryptChunkedAsync'' | byte[] ciphertext, byte[] key | Task | | ''EncryptStreamWithPqKeyAsync'' | byte[] plaintext, byte[] publicKey, int chunkSize | Task<(byte[], byte[])> | | ''DecryptStreamWithPqKeyAsync'' | byte[] kemCiphertext, byte[] encryptedData, byte[] privateKey | Task | ==== Pomoćne ==== ^ Metoda ^ Parametri ^ Povratna vrijednost ^ | ''RandomBytesAsync'' | int length | Task | | ''CreateHybridSignatureAsync'' | byte[] data, byte[] classicSig, byte[] pqPrivKey | Task | | ''DeriveTls13KeysAsync'' | byte[] sharedSecret, byte[] clientHello, byte[] serverHello | Task | ===== Potpuni primjer ===== // Blazor Component @page "/crypto-demo" @inject ICryptoProvider CryptoProvider

PQ Crypto Demo

Status: @_status

@code { private string _status = "Inicijalizacija..."; protected override async Task OnInitializedAsync() { try { await CryptoProvider.InitializeAsync(); // Key Exchange Demo var (alicePublic, alicePrivate) = await CryptoProvider.GenerateMlKemKeyPairAsync(); var (sharedSecret, ciphertext) = await CryptoProvider.EncapsulateAsync(alicePublic); var decapsulated = await CryptoProvider.DecapsulateAsync(ciphertext, alicePrivate); bool keysMatch = sharedSecret.SequenceEqual(decapsulated); // Potpis Demo var (sigPub, sigPriv) = await CryptoProvider.GenerateMlDsaKeyPairAsync(); byte[] message = Encoding.UTF8.GetBytes("Test poruka"); byte[] signature = await CryptoProvider.SignMlDsaAsync(message, sigPriv); bool isValid = await CryptoProvider.VerifyMlDsaAsync(message, signature, sigPub); _status = $"Keys match: {keysMatch}, Signature valid: {isValid}"; } catch (Exception ex) { _status = $"Greška: {ex.Message}"; } } }
===== Sigurnosne napomene ===== * **Zahtijeva .NET 8.0+** s Blazor WebAssembly * Memorija preglednika je manje sigurna od serverske memorije * Privatni ključevi ne bi se trebali dugoročno pohranjivati u pregledniku * Za osjetljive operacije: Preferirati obradu na strani servera * ''openssl.wasm'' i ''wvds-crypto.js'' moraju biti ispravno učitani **Najbolje prakse za kripto u pregledniku:** * Koristiti efemerne ključeve za šifriranje temeljeno na sesijama * Osjetljive privatne ključeve ostaviti na serveru * Ne koristiti IndexedDB/localStorage za nešifrirane ključeve * Ispravno konfigurirati CSP zaglavlja za WASM ===== Vidi također ===== * [[.:start|Providers Namespace]] * [[.:icryptoprovider|ICryptoProvider]] * [[.:nativecryptoprovider|NativeCryptoProvider]] * [[.:cryptoproviderfactory|CryptoProviderFactory]] * [[hr:int:pqcrypt:developer:integration:blazor-wasm|Blazor WASM Integracija]] ---- //Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//