Web-based OpenSSL-like random key generator that can be loaded as either:
- A minified JavaScript library (dist/webopenssl.min.js)
- With optional WASM provider (compiled OpenSSL via Emscripten) to use RAND_bytes
Create random keys similar to openssl rand -base64 32
, using secure system randomness:
- WebCrypto (browser):
crypto.getRandomValues
, backed by OS CSPRNG - Node.js (min.js UMD):
crypto.randomBytes
- Optional OpenSSL WASM module: calls
RAND_bytes
from libcrypto compiled to WebAssembly
This matches OpenSSL's security model for randomness (OS-backed CSPRNG).
- src/index.js (ESM) — readable source
- dist/webopenssl.min.js (UMD) — minified build for browser or Node
- examples/index.html — simple usage in a web page
- scripts/build-openssl-wasm.sh — builds OpenSSL libcrypto to WASM
- src/wasm/openssl_rand_wrapper.c — small wrapper that exposes
openssl_rand_bytes(...)
for Emscripten
- randBytes(length: number): Uint8Array
- randBase64(length: number): string
- randHex(length: number): string
- setProvider(provider: { name: string; randBytes(length): Uint8Array })
- setWasmModule(Module: EmscriptenModule) — configures OpenSSL WASM provider
- getProviderName(): string
- autoLoadOpenSSLWASM(options?: { url?: string; factoryGlobalName?: string }): Promise
- When OpenSSL WASM provider is loaded (openssl-wasm), additional functions are available:
- sha256(bytes: Uint8Array): Uint8Array (32 bytes)
- sha512(bytes: Uint8Array): Uint8Array (64 bytes)
- pbkdf2HmacSha256(password: Uint8Array, salt: Uint8Array, iterations: number, keyLen: number): Uint8Array
- pbkdf2HmacSha512(password: Uint8Array, salt: Uint8Array, iterations: number, keyLen: number): Uint8Array
- aes256GcmEncrypt(key: Uint8Array(32), iv: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): { ciphertext: Uint8Array, tag: Uint8Array(16) }
- aes256GcmDecrypt(key: Uint8Array(32), iv: Uint8Array, aad: Uint8Array, ciphertext: Uint8Array, tag: Uint8Array(16)): Uint8Array
Include the minified UMD bundle:
<script src="./dist/webopenssl.min.js"></script>
<script>
// Equivalent to: openssl rand -base64 32
const keyB64 = WebOpenSSL.randBase64(32);
console.log("base64 key:", keyB64);
const keyHex = WebOpenSSL.randHex(32);
console.log("hex key:", keyHex);
console.log("provider:", WebOpenSSL.getProviderName()); // "webcrypto" (default) or "openssl-wasm" if configured
</script>
If you build the OpenSSL WASM module, you can auto-load it:
<script src="./dist/webopenssl.min.js"></script>
<script>
WebOpenSSL.autoLoadOpenSSLWASM({ url: './dist/openssl-wasm/openssl_module.js' })
.then((loaded) => {
console.log("WASM loaded:", loaded);
console.log("provider:", WebOpenSSL.getProviderName()); // "openssl-wasm" if loaded
});
</script>
- The loader derives the
.wasm
URL from the JS factory URL you pass toautoLoadOpenSSLWASM
by replacing.js
with.wasm
.- Example:
./dist/openssl-wasm/openssl_module.js
→./dist/openssl-wasm/openssl_module.wasm
- Example:
- It explicitly passes
locateFile
andwasmBinaryFile
to the Emscripten factory so the.wasm
is fetched from that derived path. - This avoids relative-path issues on hosts like Vercel where asset bases differ.
- If you serve assets from a CDN or different base path, provide an absolute URL for
options.url
; the.wasm
will be fetched alongside it.
- After
npm run deploy:vercel
, open the deployed site and the browser devtools network panel. - You should see a request for
openssl_module.wasm
with:- Status 200 and Type “wasm”
- Request URL matching your JS path with
.wasm
extension
- If you see 404:
- Ensure the build produced both
dist/openssl-wasm/openssl_module.js
anddist/openssl-wasm/openssl_module.wasm
(npm run build:wasm
). - Confirm they are present in the deployed output folder (
vercel-build/dist/openssl-wasm
) before deploy. - Ensure your HTML references the JS factory using a correct path for your deployment. The included deploy script rewrites
../dist/...
todist/...
when movingexamples/index.html
to the root.
- Ensure the build produced both
- If the
.wasm
is fetched from an unexpected location, pass an absoluteoptions.url
pointing to the JS asset where you want the.wasm
to live and the loader will derive the correct.wasm
URL automatically.
import { randBase64, randHex, getProviderName, autoLoadOpenSSLWASM } from "./src/index.js";
console.log(randBase64(32));
console.log(randHex(32));
console.log(getProviderName()); // "webcrypto"
await autoLoadOpenSSLWASM({ url: "./dist/openssl-wasm/openssl_module.js" });
console.log(getProviderName()); // "openssl-wasm" if loaded
Prerequisites:
- macOS/Linux with bash, curl, tar, make, perl
- Emscripten SDK (emsdk) in PATH, or this script will fetch and activate a local copy
Steps:
- Using npm script:
- npm run build:wasm
- Or directly:
- bash scripts/build-openssl-wasm.sh
What the script does:
- Downloads OpenSSL 3.5.3
- Builds libcrypto with emconfigure/emmake (disables unsupported features in WASM)
- Compiles a small wrapper (src/wasm/openssl_rand_wrapper.c) and links against libcrypto
- Emits a modularized factory (OpenSSLModuleFactory) at dist/openssl-wasm/openssl_module.js with a .wasm sidecar
- WebOpenSSL can auto-load it via autoLoadOpenSSLWASM or manually via setWasmModule
<script src="./dist/webopenssl.min.js"></script>
<script src="./dist/openssl-wasm/openssl_module.js"></script>
<script>
OpenSSLModuleFactory().then((Module) => {
WebOpenSSL.setWasmModule(Module);
console.log("provider:", WebOpenSSL.getProviderName()); // "openssl-wasm"
console.log(WebOpenSSL.randBase64(32));
});
</script>
This repo includes an npm script that prepares a deployable folder (vercel-build) and deploys it to Vercel. It:
- Builds a fresh WASM (npm run build:wasm)
- Copies the entire project into vercel-build (excluding dev/build artifacts)
- Moves examples/index.html to vercel-build/index.html
- Rewrites relative paths so index.html references dist and src from vercel-build root
- Deploys vercel-build with the Vercel CLI
Prerequisites (one-time):
- Install Vercel CLI:
npm i -g vercel
- Login:
vercel login
- Link the deploy folder (must be done once before the first deployment):
- Ensure the folder exists:
mkdir -p vercel-build
- Link vercel-build to a Vercel project:
Follow the prompts to create/select a project and scope.
vercel link --cwd vercel-build
- Ensure the folder exists:
Deploy
- Run:
The script will:
npm run deploy:vercel
- Build fresh WASM
- Sync files into vercel-build
- Move examples/index.html to vercel-build/index.html
- Rewrite any ../dist/... and ../src/... references to dist/... and src/...
- Deploy vercel-build to production with Vercel
Notes
- If you relocate or rename examples/index.html, adjust the script at scripts/deploy-vercel.sh accordingly.
- The script preserves vercel-build/.vercel, so you only need to run vercel link once.
- You can view deployment logs and URLs in your Vercel dashboard.
- WebOpenSSL uses cryptographically secure randomness:
- Browser: WebCrypto
getRandomValues
(OS CSPRNG) - Node.js:
crypto.randomBytes
(OS CSPRNG) - OpenSSL WASM:
RAND_bytes
via libcrypto (OpenSSL's CSPRNG)
- Browser: WebCrypto
- Output length semantics mirror
openssl rand
:randBase64(n)
generates n random bytes and returns base64 encoding of those bytes.randHex(n)
generates n random bytes and returns hex encoding.
- This library focuses on secure random key generation. It is not a full re-implementation of OpenSSL.
- Building OpenSSL to WASM can be environment-sensitive. The provided script targets modern Emscripten and OpenSSL 3.5.3.
MIT