Blazor WebAssembly
│
▼
┌─────────────────┐
│ WasmCrypto- │
│ Provider │
│ (C#) │
└────────┬────────┘
│ IJSRuntime.InvokeAsync
▼
┌─────────────────┐
│ wvds-crypto.js │
│ (JavaScript) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ openssl.wasm │
│ (WebAssembly) │
└─────────────────┘
===== Eigenschaften =====
^ Eigenschaft ^ Typ ^ Beschreibung ^
| ''Name'' | string | ''%%"WASM (JS Interop)"%%'' |
| ''IsAvailable'' | bool | ''true'' wenn initialisiert |
===== Dependency Injection =====
// Program.cs (Blazor WebAssembly)
builder.Services.AddScoped(sp =>
new WasmCryptoProvider(sp.GetRequiredService()));
===== Initialisierung =====
@inject ICryptoProvider CryptoProvider
@code {
protected override async Task OnInitializedAsync()
{
await CryptoProvider.InitializeAsync();
if (CryptoProvider.IsAvailable)
{
var version = CryptoProvider.GetOpenSslVersion();
Console.WriteLine($"OpenSSL WASM: {version}");
}
}
}
===== Erforderliche JS/WASM Dateien =====
In ''wwwroot/index.html'':
===== ML-DSA Operationen =====
==== GenerateMlDsaKeyPairAsync ====
var (publicKey, privateKey) = await provider.GenerateMlDsaKeyPairAsync("ML-DSA-65");
==== SignMlDsaAsync ====
byte[] data = Encoding.UTF8.GetBytes("Browser-signierte Daten");
byte[] signature = await provider.SignMlDsaAsync(data, privateKey);
==== VerifyMlDsaAsync ====
bool isValid = await provider.VerifyMlDsaAsync(data, signature, publicKey);
===== ML-KEM Operationen =====
==== 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 Operationen =====
==== Pbkdf2Async ====
PBKDF2 über 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 mit PQ-verstärktem Salt.
byte[] key = await provider.Pbkdf2WithPqSaltAsync(
password: "UserPassword",
baseSalt: baseSalt,
pqPublicKey: recipientPqPublicKey,
iterations: 100000,
outputLength: 32);
==== Argon2idAsync ====
Memory-hard KDF via OpenSSL WASM.
byte[] key = await provider.Argon2idAsync(
password: passwordBytes,
salt: salt,
outputLength: 32,
iterations: 3,
memoryKiB: 65536,
parallelism: 4);
===== Stream/Chunked Encryption =====
==== EncryptChunkedAsync / DecryptChunkedAsync ====
Für große Datenmengen mit Chunk-Verarbeitung.
byte[] key = await provider.RandomBytesAsync(32);
// Verschlüsseln
byte[] encrypted = await provider.EncryptChunkedAsync(
plaintext,
key,
chunkSize: 65536); // 64 KB Chunks
// Entschlüsseln
byte[] decrypted = await provider.DecryptChunkedAsync(encrypted, key);
==== EncryptStreamWithPqKeyAsync / DecryptStreamWithPqKeyAsync ====
Kombiniert ML-KEM Key Exchange mit chunked Encryption.
// Verschlüsseln für Empfänger
var (kemCiphertext, encryptedData) = await provider.EncryptStreamWithPqKeyAsync(
plaintext,
recipientPublicKey,
chunkSize: 65536);
// Entschlüsseln
byte[] decrypted = await provider.DecryptStreamWithPqKeyAsync(
kemCiphertext,
encryptedData,
privateKey);
===== HKDF Operationen =====
==== HkdfExtractAsync ====
byte[] prk = await provider.HkdfExtractAsync(salt, inputKeyMaterial);
==== HkdfExpandAsync ====
byte[] okm = await provider.HkdfExpandAsync(prk, info, outputLength: 32);
==== HkdfDeriveKeyAsync ====
Extract + Expand in einem Schritt.
byte[] key = await provider.HkdfDeriveKeyAsync(
ikm: sharedSecret,
length: 32,
salt: optionalSalt,
info: contextInfo);
==== DeriveHybridKeyAsync ====
Kombiniert klassisches und PQ Secret.
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);
// Zugriff auf abgeleitete Secrets
var clientKey = keys.ClientHandshakeTrafficSecret;
var serverKey = keys.ServerHandshakeTrafficSecret;
===== Hybrid Signatures =====
==== CreateHybridSignatureAsync ====
Erstellt hybride Signatur aus klassischer Signatur und ML-DSA.
// Klassische Signatur erstellen (z.B. ECDSA)
byte[] classicSig = CreateEcdsaSignature(data);
// Hybrid-Signatur erstellen
byte[] hybridSig = await provider.CreateHybridSignatureAsync(
data,
classicSig,
mlDsaPrivateKey);
===== Utility Methoden =====
==== RandomBytesAsync ====
Kryptographisch sichere Zufallszahlen via Web Crypto API.
byte[] random = await provider.RandomBytesAsync(32);
===== Zertifikat-Operationen =====
==== CreateEphemeralCertificateAsync ====
byte[] certBytes = await provider.CreateEphemeralCertificateAsync(
"CN=Browser Certificate",
TimeSpan.FromHours(1),
mlDsaPrivateKey);
==== SignCertificateAsync ====
byte[] signedCert = await provider.SignCertificateAsync(tbsCertificate, privateKey);
===== Methoden-Übersicht =====
==== ML-DSA ====
^ Methode ^ Parameter ^ Rückgabe ^
| ''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 = "Initializing...";
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);
// Signatur Demo
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 = $"Error: {ex.Message}";
}
}
}
===== Sicherheitshinweise =====