Blazor WebAssembly
│
▼
┌─────────────────┐
│ WasmCrypto- │
│ Provider │
│ (C#) │
└────────┬────────┘
│ IJSRuntime.InvokeAsync
▼
┌─────────────────┐
│ wvds-crypto.js │
│ (JavaScript) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ openssl.wasm │
│ (WebAssembly) │
└─────────────────┘
===== Lastnosti =====
^ Lastnost ^ Tip ^ Opis ^
| ''Name'' | string | ''%%"WASM (JS Interop)"%%'' |
| ''IsAvailable'' | bool | ''true'' če je inicializiran |
===== Dependency Injection =====
// Program.cs (Blazor WebAssembly)
builder.Services.AddScoped(sp =>
new WasmCryptoProvider(sp.GetRequiredService()));
===== Inicializacija =====
@inject ICryptoProvider CryptoProvider
@code {
protected override async Task OnInitializedAsync()
{
await CryptoProvider.InitializeAsync();
if (CryptoProvider.IsAvailable)
{
var version = CryptoProvider.GetOpenSslVersion();
Console.WriteLine($"OpenSSL WASM: {version}");
}
}
}
===== Zahtevane JS/WASM datoteke =====
V ''wwwroot/index.html'':
===== Operacije ML-DSA =====
==== GenerateMlDsaKeyPairAsync ====
var (publicKey, privateKey) = await provider.GenerateMlDsaKeyPairAsync("ML-DSA-65");
==== SignMlDsaAsync ====
byte[] data = Encoding.UTF8.GetBytes("V brskalniku podpisani podatki");
byte[] signature = await provider.SignMlDsaAsync(data, privateKey);
==== VerifyMlDsaAsync ====
bool isValid = await provider.VerifyMlDsaAsync(data, signature, publicKey);
===== Operacije ML-KEM =====
==== 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);
===== Operacije izpeljave ključev =====
==== Pbkdf2Async ====
PBKDF2 preko Web Crypto API.
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-okrepljeno soljo.
byte[] key = await provider.Pbkdf2WithPqSaltAsync(
password: "UserPassword",
baseSalt: baseSalt,
pqPublicKey: recipientPqPublicKey,
iterations: 100000,
outputLength: 32);
==== Argon2idAsync ====
Memory-hard KDF preko 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 kolicine podatkov s chunk-obdelavo.
byte[] key = await provider.RandomBytesAsync(32);
// Šifriranje
byte[] encrypted = await provider.EncryptChunkedAsync(
plaintext,
key,
chunkSize: 65536); // 64 KB chunki
// Dešifriranje
byte[] decrypted = await provider.DecryptChunkedAsync(encrypted, key);
==== EncryptStreamWithPqKeyAsync / DecryptStreamWithPqKeyAsync ====
Kombinira ML-KEM izmenjavo ključev s chunk-šifriranjem.
// Šifriranje za prejemnika
var (kemCiphertext, encryptedData) = await provider.EncryptStreamWithPqKeyAsync(
plaintext,
recipientPublicKey,
chunkSize: 65536);
// Dešifriranje
byte[] decrypted = await provider.DecryptStreamWithPqKeyAsync(
kemCiphertext,
encryptedData,
privateKey);
===== Operacije HKDF =====
==== HkdfExtractAsync ====
byte[] prk = await provider.HkdfExtractAsync(salt, inputKeyMaterial);
==== HkdfExpandAsync ====
byte[] okm = await provider.HkdfExpandAsync(prk, info, outputLength: 32);
==== HkdfDeriveKeyAsync ====
Extract + Expand v enem koraku.
byte[] key = await provider.HkdfDeriveKeyAsync(
ikm: sharedSecret,
length: 32,
salt: optionalSalt,
info: contextInfo);
==== DeriveHybridKeyAsync ====
Kombinira klasično in PQ skrivnost.
byte[] hybridKey = await provider.DeriveHybridKeyAsync(
classicSecret: ecdhSecret,
pqSecret: mlKemSecret,
outputLength: 32);
===== TLS 1.3 izpeljava ključev =====
==== DeriveTls13KeysAsync ====
Tls13KeyMaterial keys = await provider.DeriveTls13KeysAsync(
sharedSecret,
clientHello,
serverHello);
// Dostop do izpeljanih skrivnosti
var clientKey = keys.ClientHandshakeTrafficSecret;
var serverKey = keys.ServerHandshakeTrafficSecret;
===== Hibridni podpisi =====
==== CreateHybridSignatureAsync ====
Ustvari hibridni podpis iz klasičnega podpisa in ML-DSA.
// Ustvarjanje klasičnega podpisa (npr. ECDSA)
byte[] classicSig = CreateEcdsaSignature(data);
// Ustvarjanje hibridnega podpisa
byte[] hybridSig = await provider.CreateHybridSignatureAsync(
data,
classicSig,
mlDsaPrivateKey);
===== Pomožne metode =====
==== RandomBytesAsync ====
Kriptografsko varna naključna števila preko Web Crypto API.
byte[] random = await provider.RandomBytesAsync(32);
===== Operacije s certifikati =====
==== CreateEphemeralCertificateAsync ====
byte[] certBytes = await provider.CreateEphemeralCertificateAsync(
"CN=Certifikat brskalnika",
TimeSpan.FromHours(1),
mlDsaPrivateKey);
==== SignCertificateAsync ====
byte[] signedCert = await provider.SignCertificateAsync(tbsCertificate, privateKey);
===== Pregled metod =====
==== ML-DSA ====
^ Metoda ^ Parametri ^ Vrnjeno ^
| ''GenerateMlDsaKeyPairAsync'' | string algorithm | Task<(byte[], byte[])> |
| ''SignMlDsaAsync'' | byte[] data, byte[] privateKey | Task
// Blazor komponenta
@page "/crypto-demo"
@inject ICryptoProvider CryptoProvider
PQ Crypto Demo
Status: @_status
@code {
private string _status = "Inicializacija...";
protected override async Task OnInitializedAsync()
{
try
{
await CryptoProvider.InitializeAsync();
// Demo izmenjave ključev
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);
// Demo podpisa
var (sigPub, sigPriv) =
await CryptoProvider.GenerateMlDsaKeyPairAsync();
byte[] message = Encoding.UTF8.GetBytes("Testno sporočilo");
byte[] signature = await CryptoProvider.SignMlDsaAsync(message, sigPriv);
bool isValid = await CryptoProvider.VerifyMlDsaAsync(message, signature, sigPub);
_status = $"Ključi se ujemajo: {keysMatch}, Podpis veljaven: {isValid}";
}
catch (Exception ex)
{
_status = $"Napaka: {ex.Message}";
}
}
}
===== Varnostni nasveti =====