Blazor WebAssembly
│
▼
┌─────────────────┐
│ WasmCrypto- │
│ Provider │
│ (C#) │
└────────┬────────┘
│ IJSRuntime.InvokeAsync
▼
┌─────────────────┐
│ wvds-crypto.js │
│ (JavaScript) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ openssl.wasm │
│ (WebAssembly) │
└─────────────────┘
===== Proprieta =====
^ Proprieta ^ Tipo ^ Descrizione ^
| ''Name'' | string | ''%%"WASM (JS Interop)"%%'' |
| ''IsAvailable'' | bool | ''true'' se inizializzato |
===== Dependency Injection =====
// Program.cs (Blazor WebAssembly)
builder.Services.AddScoped(sp =>
new WasmCryptoProvider(sp.GetRequiredService()));
===== Inizializzazione =====
@inject ICryptoProvider CryptoProvider
@code {
protected override async Task OnInitializedAsync()
{
await CryptoProvider.InitializeAsync();
if (CryptoProvider.IsAvailable)
{
var version = CryptoProvider.GetOpenSslVersion();
Console.WriteLine($"OpenSSL WASM: {version}");
}
}
}
===== File JS/WASM richiesti =====
In ''wwwroot/index.html'':
===== Operazioni ML-DSA =====
==== GenerateMlDsaKeyPairAsync ====
var (publicKey, privateKey) = await provider.GenerateMlDsaKeyPairAsync("ML-DSA-65");
==== SignMlDsaAsync ====
byte[] data = Encoding.UTF8.GetBytes("Dati firmati dal browser");
byte[] signature = await provider.SignMlDsaAsync(data, privateKey);
==== VerifyMlDsaAsync ====
bool isValid = await provider.VerifyMlDsaAsync(data, signature, publicKey);
===== Operazioni 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);
===== Operazioni Key Derivation =====
==== Pbkdf2Async ====
PBKDF2 tramite 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 con Salt rinforzato PQ.
byte[] key = await provider.Pbkdf2WithPqSaltAsync(
password: "UserPassword",
baseSalt: baseSalt,
pqPublicKey: recipientPqPublicKey,
iterations: 100000,
outputLength: 32);
==== Argon2idAsync ====
KDF memory-hard tramite OpenSSL WASM.
byte[] key = await provider.Argon2idAsync(
password: passwordBytes,
salt: salt,
outputLength: 32,
iterations: 3,
memoryKiB: 65536,
parallelism: 4);
===== Crittografia Stream/Chunked =====
==== EncryptChunkedAsync / DecryptChunkedAsync ====
Per grandi quantita di dati con elaborazione a chunk.
byte[] key = await provider.RandomBytesAsync(32);
// Crittografare
byte[] encrypted = await provider.EncryptChunkedAsync(
plaintext,
key,
chunkSize: 65536); // Chunk da 64 KB
// Decrittografare
byte[] decrypted = await provider.DecryptChunkedAsync(encrypted, key);
==== EncryptStreamWithPqKeyAsync / DecryptStreamWithPqKeyAsync ====
Combina ML-KEM Key Exchange con crittografia chunked.
// Crittografare per destinatario
var (kemCiphertext, encryptedData) = await provider.EncryptStreamWithPqKeyAsync(
plaintext,
recipientPublicKey,
chunkSize: 65536);
// Decrittografare
byte[] decrypted = await provider.DecryptStreamWithPqKeyAsync(
kemCiphertext,
encryptedData,
privateKey);
===== Operazioni HKDF =====
==== HkdfExtractAsync ====
byte[] prk = await provider.HkdfExtractAsync(salt, inputKeyMaterial);
==== HkdfExpandAsync ====
byte[] okm = await provider.HkdfExpandAsync(prk, info, outputLength: 32);
==== HkdfDeriveKeyAsync ====
Extract + Expand in un unico passaggio.
byte[] key = await provider.HkdfDeriveKeyAsync(
ikm: sharedSecret,
length: 32,
salt: optionalSalt,
info: contextInfo);
==== DeriveHybridKeyAsync ====
Combina secret classico e PQ.
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);
// Accesso ai secrets derivati
var clientKey = keys.ClientHandshakeTrafficSecret;
var serverKey = keys.ServerHandshakeTrafficSecret;
===== Firme ibride =====
==== CreateHybridSignatureAsync ====
Crea firma ibrida da firma classica e ML-DSA.
// Creare firma classica (es. ECDSA)
byte[] classicSig = CreateEcdsaSignature(data);
// Creare firma ibrida
byte[] hybridSig = await provider.CreateHybridSignatureAsync(
data,
classicSig,
mlDsaPrivateKey);
===== Metodi utility =====
==== RandomBytesAsync ====
Numeri casuali crittograficamente sicuri tramite Web Crypto API.
byte[] random = await provider.RandomBytesAsync(32);
===== Operazioni certificati =====
==== CreateEphemeralCertificateAsync ====
byte[] certBytes = await provider.CreateEphemeralCertificateAsync(
"CN=Browser Certificate",
TimeSpan.FromHours(1),
mlDsaPrivateKey);
==== SignCertificateAsync ====
byte[] signedCert = await provider.SignCertificateAsync(tbsCertificate, privateKey);
===== Panoramica metodi =====
==== ML-DSA ====
^ Metodo ^ Parametri ^ Ritorno ^
| ''GenerateMlDsaKeyPairAsync'' | string algorithm | Task<(byte[], byte[])> |
| ''SignMlDsaAsync'' | byte[] data, byte[] privateKey | Task
// Componente Blazor
@page "/crypto-demo"
@inject ICryptoProvider CryptoProvider
PQ Crypto Demo
Status: @_status
@code {
private string _status = "Inizializzazione...";
protected override async Task OnInitializedAsync()
{
try
{
await CryptoProvider.InitializeAsync();
// Demo Key Exchange
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 firma
var (sigPub, sigPriv) =
await CryptoProvider.GenerateMlDsaKeyPairAsync();
byte[] message = Encoding.UTF8.GetBytes("Test Message");
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 = $"Errore: {ex.Message}";
}
}
}
===== Note di sicurezza =====