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