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<ICryptoProvider>(sp =>
    new WasmCryptoProvider(sp.GetRequiredService<IJSRuntime>()));

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:

<head>
    <!-- OpenSSL WASM Module -->
    <script src="_content/WvdS.Crypto/openssl.js"></script>
 
    <!-- WvdS Crypto Wrapper -->
    <script src="_content/WvdS.Crypto/wvds-crypto.js"></script>
</head>

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<byte[]>
VerifyMlDsaAsync byte[] data, byte[] signature, byte[] publicKey Task<bool>

ML-KEM

Metoda Parametri Povratna vrijednost
GenerateMlKemKeyPairAsync string algorithm Task<(byte[], byte[])>
EncapsulateAsync byte[] publicKey Task<(byte[], byte[])>
DecapsulateAsync byte[] ciphertext, byte[] privateKey Task<byte[]>

Key Derivation

Metoda Parametri Povratna vrijednost
Pbkdf2Async string password, byte[] salt, int iterations, int outputLength, string hash Task<byte[]>
Pbkdf2WithPqSaltAsync string password, byte[] baseSalt, byte[] pqPublicKey, int iterations, int outputLength Task<byte[]>
Argon2idAsync byte[]/string password, byte[] salt, int outputLength, int iterations, int memoryKiB, int parallelism Task<byte[]>

HKDF

Metoda Parametri Povratna vrijednost
HkdfExtractAsync byte[] salt, byte[] ikm Task<byte[]>
HkdfExpandAsync byte[] prk, byte[] info, int length Task<byte[]>
HkdfDeriveKeyAsync byte[] ikm, int length, byte[]? salt, byte[]? info Task<byte[]>
DeriveHybridKeyAsync byte[] classicSecret, byte[] pqSecret, int outputLength Task<byte[]>

Šifriranje

Metoda Parametri Povratna vrijednost
EncryptChunkedAsync byte[] plaintext, byte[] key, int chunkSize Task<byte[]>
DecryptChunkedAsync byte[] ciphertext, byte[] key Task<byte[]>
EncryptStreamWithPqKeyAsync byte[] plaintext, byte[] publicKey, int chunkSize Task<(byte[], byte[])>
DecryptStreamWithPqKeyAsync byte[] kemCiphertext, byte[] encryptedData, byte[] privateKey Task<byte[]>

Pomoćne

Metoda Parametri Povratna vrijednost
RandomBytesAsync int length Task<byte[]>
CreateHybridSignatureAsync byte[] data, byte[] classicSig, byte[] pqPrivKey Task<byte[]>
DeriveTls13KeysAsync byte[] sharedSecret, byte[] clientHello, byte[] serverHello Task<Tls13KeyMaterial>

Potpuni primjer

// Blazor Component
@page "/crypto-demo"
@inject ICryptoProvider CryptoProvider
 
<h3>PQ Crypto Demo</h3>
<p>Status: @_status</p>
 
@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


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional

Zuletzt geändert: 30.01.2026. u 01:16