====== 3.3 WASM Build for Blazor ======
This guide explains how to compile OpenSSL for Blazor WebAssembly.
----
===== What is WebAssembly? =====
**WebAssembly (WASM)** is a binary format that runs in the browser. It enables:
* High-performance code in the browser
* Using languages like C/C++ on the web
* Blazor WebAssembly applications
**When do I need WASM?**
| Application Type | WASM needed? |
|------------------|--------------|
| Blazor WebAssembly | **Yes** |
| Blazor Server | No (uses Windows/Linux build) |
| ASP.NET Core API | No |
| Desktop App (.NET) | No |
----
===== Prerequisites =====
In addition to standard tools you need:
* ☑ [[.:..vorbereitung:wsl-einrichten|WSL2 with Ubuntu/Fedora]]
* ☑ [[.:..vorbereitung:emscripten|Emscripten SDK]]
WASM builds are only possible under Linux/WSL, not directly under Windows!
----
===== Build Overview =====
The WASM build creates:
* ''openssl.js'' - JavaScript loader
* ''openssl.wasm'' - WebAssembly module
* C wrapper for Post-Quantum functions
----
===== Build Steps =====
==== Step 1: Open WSL ====
# Open WSL terminal
wsl
==== Step 2: Activate Emscripten ====
# Load Emscripten environment
source /opt/emsdk/emsdk_env.sh
# Verify
emcc --version
# Should show: emcc (Emscripten gcc/clang-like replacement) 3.x.x
==== Step 3: Prepare Build Directory ====
# Create directories
mkdir -p /mnt/d/Projects/openssl-3.6.0/wasm-build
mkdir -p /mnt/d/Projects/openssl-3.6.0/wasm-install
cd /mnt/d/Projects/openssl-3.6.0/wasm-build
==== Step 4: Configure OpenSSL for WASM ====
emconfigure /mnt/d/Projects/openssl-3.6.0/src/Configure \
linux-generic32 \
--prefix=/mnt/d/Projects/openssl-3.6.0/wasm-install \
--openssldir=/mnt/d/Projects/openssl-3.6.0/wasm-install/ssl \
no-asm \
no-threads \
no-shared \
no-dso \
no-engine \
no-hw \
no-async \
no-sock \
no-dgram \
no-tests \
no-apps \
-DOPENSSL_NO_SECURE_MEMORY \
CC=emcc \
AR=emar \
RANLIB=emranlib
**Explanation of options:**
| Option | Meaning |
|--------|---------|
| ''linux-generic32'' | Generic 32-bit platform |
| ''no-asm'' | No assembly (WASM can't use x86 assembly) |
| ''no-threads'' | No threads (Web Workers separate) |
| ''no-shared'' | Static library only |
| ''no-sock'' | No socket support |
| ''no-tests'' | Don't build tests |
| ''no-apps'' | No openssl CLI tool |
==== Step 5: Compile ====
emmake make -j$(nproc) build_libs
==== Step 6: Install ====
emmake make install_sw
----
===== Create JavaScript Wrapper =====
For integration into Blazor we need a wrapper:
==== wvds_crypto_wrapper.c ====
// WvdS Crypto WASM Wrapper
#include
#include
#include
#include
#include
#include
// Initialization
EMSCRIPTEN_KEEPALIVE
int wvds_init(void) {
OPENSSL_init_crypto(
OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
OPENSSL_INIT_ADD_ALL_CIPHERS |
OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
return 1;
}
// OpenSSL Version
EMSCRIPTEN_KEEPALIVE
const char* wvds_get_version(void) {
return OPENSSL_VERSION_TEXT;
}
// ML-DSA Key Generation
EMSCRIPTEN_KEEPALIVE
int wvds_mldsa_keygen(const char* algorithm,
unsigned char** pub_key, int* pub_len,
unsigned char** priv_key, int* priv_len) {
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
int ret = 0;
// Algorithm name for OpenSSL
const char* ossl_alg = algorithm;
if (strcmp(algorithm, "ML-DSA-44") == 0) ossl_alg = "mldsa44";
else if (strcmp(algorithm, "ML-DSA-65") == 0) ossl_alg = "mldsa65";
else if (strcmp(algorithm, "ML-DSA-87") == 0) ossl_alg = "mldsa87";
ctx = EVP_PKEY_CTX_new_from_name(NULL, ossl_alg, NULL);
if (!ctx) goto err;
if (EVP_PKEY_keygen_init(ctx) <= 0) goto err;
if (EVP_PKEY_keygen(ctx, &pkey) <= 0) goto err;
// Export public key
*pub_len = i2d_PUBKEY(pkey, NULL);
*pub_key = malloc(*pub_len);
unsigned char *p = *pub_key;
i2d_PUBKEY(pkey, &p);
// Export private key
*priv_len = i2d_PrivateKey(pkey, NULL);
*priv_key = malloc(*priv_len);
p = *priv_key;
i2d_PrivateKey(pkey, &p);
ret = 1;
err:
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
return ret;
}
// Free memory
EMSCRIPTEN_KEEPALIVE
void wvds_free(void* ptr) {
free(ptr);
}
==== Compile Wrapper ====
INSTALL_DIR=/mnt/d/Projects/openssl-3.6.0/wasm-install
OUTPUT=/mnt/d/Projects/openssl-3.6.0/wasm-build
emcc $OUTPUT/wvds_crypto_wrapper.c \
-I"$INSTALL_DIR/include" \
-L"$INSTALL_DIR/lib" \
-lcrypto \
-Os \
-s WASM=1 \
-s MODULARIZE=1 \
-s EXPORT_NAME="OpenSSLModule" \
-s EXPORTED_FUNCTIONS='["_wvds_init","_wvds_get_version","_wvds_mldsa_keygen","_wvds_free","_malloc","_free"]' \
-s EXPORTED_RUNTIME_METHODS='["ccall","cwrap","getValue","setValue","UTF8ToString"]' \
-s ALLOW_MEMORY_GROWTH=1 \
-o "$OUTPUT/openssl.js"
----
===== Result =====
After the build:
wasm-build/
├── openssl.js # JavaScript Loader (~150 KB)
└── openssl.wasm # WebAssembly Module (~2 MB)
----
===== Integrate into Blazor =====
==== 1. Copy Files ====
cp openssl.js openssl.wasm /mnt/d/MyProject/wwwroot/
==== 2. Load in index.html ====
==== 3. Call from Blazor ====
// In your Blazor component
@inject IJSRuntime JS
public async Task GetOpenSslVersion()
{
return await JS.InvokeAsync("eval",
"cryptoModule.ccall('wvds_get_version', 'string', [], [])");
}
----
===== Continue to =====
* [[.:vorbereitung:emscripten|Install Emscripten SDK]]
* [[.:integration:blazor-wasm|Blazor WASM Integration]]
* [[.:build:start|Back to Build Overview]]
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//