WASM API Reference
Complete API documentation for MetaMUI Crypto Primitives in WebAssembly.
Installation
npm install @metamui/crypto-wasm
# or
yarn add @metamui/crypto-wasm
# or
pnpm add @metamui/crypto-wasm
Quick Start
import init, { Ed25519, ChaCha20Poly1305, Blake3 } from '@metamui/crypto-wasm';
// Initialize WASM module
await init();
// Generate keypair
const keypair = Ed25519.generateKeypair();
// Sign message
const message = new TextEncoder().encode("Hello");
const signature = Ed25519.sign(message, keypair.privateKey);
// Verify signature
const isValid = Ed25519.verify(signature, message, keypair.publicKey);
API Documentation
For detailed API documentation, see:
Initialization
Browser
import init from '@metamui/crypto-wasm';
// Auto-detect WASM URL
await init();
// Or specify custom URL
await init('/path/to/metamui_crypto_wasm_bg.wasm');
Node.js
import { readFile } from 'fs/promises';
import init from '@metamui/crypto-wasm';
const wasmBuffer = await readFile('./node_modules/@metamui/crypto-wasm/metamui_crypto_wasm_bg.wasm');
await init(wasmBuffer);
Web Workers
// worker.js
import init, * as crypto from '@metamui/crypto-wasm';
self.addEventListener('message', async (event) => {
if (!self.cryptoInitialized) {
await init();
self.cryptoInitialized = true;
}
const { type, data } = event.data;
switch (type) {
case 'hash':
const hash = crypto.Blake3.hash(data);
self.postMessage({ type: 'hash', result: hash });
break;
// ... other operations
}
});
Available Functions
Hash Functions
import { SHA256, SHA512, Blake2b, Blake3, SHAKE256 } from '@metamui/crypto-wasm';
// Simple hashing
const hash = SHA256.hash(data);
const blake3Hash = Blake3.hash(data);
// Streaming hash
const hasher = Blake3.createHasher();
hasher.update(chunk1);
hasher.update(chunk2);
const finalHash = hasher.finalize();
// SHAKE256 (XOF)
const output = SHAKE256.hash(data, outputLength);
Digital Signatures
import { Ed25519, Sr25519, Dilithium, Falcon512 } from '@metamui/crypto-wasm';
// Ed25519
const keypair = Ed25519.generateKeypair();
const signature = Ed25519.sign(message, keypair.privateKey);
const isValid = Ed25519.verify(signature, message, keypair.publicKey);
// Post-quantum signatures
const pqKeypair = Dilithium.generateKeypair();
const pqSignature = Dilithium.sign(message, pqKeypair.privateKey);
Encryption
import { ChaCha20Poly1305, AES256, ARIA256 } from '@metamui/crypto-wasm';
// ChaCha20-Poly1305
const key = ChaCha20Poly1305.generateKey();
const encrypted = ChaCha20Poly1305.encrypt(plaintext, key);
const decrypted = ChaCha20Poly1305.decrypt(
encrypted.ciphertext,
encrypted.nonce,
key
);
// AES-256-GCM
const aesKey = AES256.generateKey();
const aesEncrypted = AES256.encrypt(plaintext, aesKey);
Key Exchange
import { X25519, MLKem768 } from '@metamui/crypto-wasm';
// X25519 ECDH
const alice = X25519.generateKeypair();
const bob = X25519.generateKeypair();
const sharedSecret = X25519.computeSharedSecret(
alice.privateKey,
bob.publicKey
);
// Post-quantum KEM
const kemKeypair = MLKem768.generateKeypair();
const encapsulated = MLKem768.encapsulate(kemKeypair.publicKey);
const sharedSecret2 = MLKem768.decapsulate(
encapsulated.ciphertext,
kemKeypair.privateKey
);
Key Derivation
import { Argon2, PBKDF2, HKDF } from '@metamui/crypto-wasm';
// Password hashing
const salt = Argon2.generateSalt();
const hash = Argon2.hash(
password,
salt,
256 * 1024, // memory in KB
4, // iterations
2 // parallelism
);
// Key derivation
const derivedKey = HKDF.derive(
inputKey,
salt,
info,
32 // output length
);
Memory Management
WASM memory is automatically managed, but you can optimize usage:
// Memory is automatically freed after use
const hash = Blake3.hash(largeData);
// For streaming operations, memory is reused
const hasher = Blake3.createHasher();
for (const chunk of chunks) {
hasher.update(chunk); // Reuses internal buffer
}
const finalHash = hasher.finalize();
hasher.free(); // Explicitly free if needed
Performance Optimization
Batch Operations
// Process multiple items efficiently
const hashes = Blake3.batchHash(dataArray);
const signatures = Ed25519.batchSign(messages, privateKey);
const results = Ed25519.batchVerify(signatures, messages, publicKeys);
Streaming Large Files
async function hashLargeFile(file) {
const hasher = Blake3.createHasher();
const reader = file.stream().getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
hasher.update(value);
}
return hasher.finalize();
} finally {
hasher.free();
}
}
Web Workers Pool
class CryptoWorkerPool {
constructor(poolSize = 4) {
this.workers = Array(poolSize).fill(null).map(() => {
const worker = new Worker('/crypto-worker.js');
return { worker, busy: false };
});
}
async execute(operation, data) {
const available = this.workers.find(w => !w.busy);
if (!available) {
// Wait for next available worker
await new Promise(resolve => setTimeout(resolve, 10));
return this.execute(operation, data);
}
available.busy = true;
return new Promise((resolve, reject) => {
available.worker.onmessage = (e) => {
available.busy = false;
resolve(e.data.result);
};
available.worker.onerror = (e) => {
available.busy = false;
reject(e);
};
available.worker.postMessage({ operation, data });
});
}
}
Browser Compatibility
Feature Detection
// Check WebAssembly support
if (typeof WebAssembly === 'undefined') {
console.error('WebAssembly not supported');
// Fall back to pure JS implementation
}
// Check for required features
const features = {
bigInt: typeof BigInt !== 'undefined',
sharedArrayBuffer: typeof SharedArrayBuffer !== 'undefined',
atomics: typeof Atomics !== 'undefined'
};
Polyfills
// TextEncoder/TextDecoder polyfill for older browsers
if (typeof TextEncoder === 'undefined') {
await import('fast-text-encoding');
}
Security Considerations
Content Security Policy
<!-- Allow WASM execution -->
<meta http-equiv="Content-Security-Policy"
content="script-src 'self' 'wasm-unsafe-eval'">
Secure Random
// Uses crypto.getRandomValues() internally
const randomBytes = crypto.secureRandom(32);
// For Node.js, uses crypto.randomBytes
Examples
Browser Encryption
class BrowserCrypto {
constructor() {
this.initialized = false;
}
async init() {
if (!this.initialized) {
await init();
this.initialized = true;
}
}
async encryptData(data, password) {
await this.init();
// Derive key from password
const salt = Argon2.generateSalt();
const key = Argon2.deriveKey(password, salt, 32);
// Encrypt data
const encrypted = ChaCha20Poly1305.encrypt(data, key);
// Return encrypted package
return {
salt: Array.from(salt),
nonce: Array.from(encrypted.nonce),
ciphertext: Array.from(encrypted.ciphertext)
};
}
async decryptData(encryptedPackage, password) {
await this.init();
// Reconstruct arrays
const salt = new Uint8Array(encryptedPackage.salt);
const nonce = new Uint8Array(encryptedPackage.nonce);
const ciphertext = new Uint8Array(encryptedPackage.ciphertext);
// Derive same key
const key = Argon2.deriveKey(password, salt, 32);
// Decrypt
return ChaCha20Poly1305.decrypt(ciphertext, nonce, key);
}
}
IndexedDB Integration
class SecureIndexedDB {
constructor(dbName) {
this.dbName = dbName;
this.key = null;
}
async init(password) {
await init(); // Initialize WASM
// Derive database encryption key
const salt = localStorage.getItem('db_salt') || (() => {
const newSalt = Argon2.generateSalt();
localStorage.setItem('db_salt', btoa(String.fromCharCode(...newSalt)));
return newSalt;
})();
this.key = Argon2.deriveKey(password, salt, 32);
}
async store(key, value) {
const data = JSON.stringify(value);
const encrypted = AES256.encrypt(
new TextEncoder().encode(data),
this.key
);
// Store in IndexedDB
const db = await this.openDB();
const tx = db.transaction(['data'], 'readwrite');
await tx.objectStore('data').put({
key,
ciphertext: encrypted.ciphertext,
nonce: encrypted.nonce
});
}
async retrieve(key) {
const db = await this.openDB();
const tx = db.transaction(['data'], 'readonly');
const record = await tx.objectStore('data').get(key);
if (!record) return null;
const decrypted = AES256.decrypt(
record.ciphertext,
record.nonce,
this.key
);
return JSON.parse(new TextDecoder().decode(decrypted));
}
}
Troubleshooting
Common Issues
WASM not loading
// Check MIME type
// Server must serve .wasm files with: application/wasm
// Webpack config
module.exports = {
experiments: {
asyncWebAssembly: true
}
};
Memory errors
// Increase memory if needed
const memory = new WebAssembly.Memory({
initial: 256, // 16MB
maximum: 4096 // 256MB
});
Performance issues
// Use streaming instantiation
const response = await fetch('/path/to/module.wasm');
const { instance } = await WebAssembly.instantiateStreaming(response);