====== 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//