fix: back WASI random_get with crypto.getRandomValues #23

Merged
jorijnvdgraaf merged 1 commit from claude/issue-22 into master 2026-06-02 02:14:58 +02:00
Member

Summary

The WASI random_get import in wasi-runtime/runtime.js was stubbed to return success (0) without writing any bytes into the target buffer. Every std::random_device user (or any random_get caller) therefore got all-zero "randomness".

This bit 3DForts: every tab generated an identical all-zero peer id from std::random_device, colliding WebRTC signaling routing (Catcrafts/3DForts#50).

Fix

  • Fill the destination buffer from crypto.getRandomValues (a CSPRNG).
  • Chunk at 65536 bytes to stay under WebCrypto's per-call quota (QuotaExceededError above that), re-viewing memory per chunk so a detached/grown buffer is handled.
  • Add random_get to the bind list — it now touches this.instance.exports.memory.

Testing

  • crafter-build test — all 12 tests pass (incl. WasiBrowserRuntime).
  • Exercised the exact random_get impl in Firefox against a simulated wasm WebAssembly.Memory: returns 0, writes non-zero bytes, two consecutive calls differ (real entropy), and a 100000-byte buffer is fully filled past the 65536 chunk boundary (verifies chunking).

Resolves #22

## Summary The WASI `random_get` import in `wasi-runtime/runtime.js` was stubbed to return success (`0`) without writing any bytes into the target buffer. Every `std::random_device` user (or any `random_get` caller) therefore got all-zero "randomness". This bit 3DForts: every tab generated an identical all-zero peer id from `std::random_device`, colliding WebRTC signaling routing (Catcrafts/3DForts#50). ## Fix - Fill the destination buffer from `crypto.getRandomValues` (a CSPRNG). - Chunk at 65536 bytes to stay under WebCrypto's per-call quota (`QuotaExceededError` above that), re-viewing memory per chunk so a detached/grown buffer is handled. - Add `random_get` to the `bind` list — it now touches `this.instance.exports.memory`. ## Testing - `crafter-build test` — all 12 tests pass (incl. `WasiBrowserRuntime`). - Exercised the exact `random_get` impl in Firefox against a simulated wasm `WebAssembly.Memory`: returns `0`, writes non-zero bytes, two consecutive calls differ (real entropy), and a 100000-byte buffer is fully filled past the 65536 chunk boundary (verifies chunking). Resolves #22
fix: back WASI random_get with crypto.getRandomValues
All checks were successful
CI / build-test-release (pull_request) Successful in 7m50s
08c28a46b7
The random_get import was stubbed to return success without writing any
bytes, so every std::random_device user in wasm got all-zero
"randomness". This collided WebRTC peer ids across browser tabs in
3DForts (Catcrafts/3DForts#50).

Fill the target buffer from crypto.getRandomValues (a CSPRNG), chunking
at 65536 bytes to stay under WebCrypto's per-call quota, and add
random_get to the bind list since it now touches this.instance.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jorijnvdgraaf deleted branch claude/issue-22 2026-06-02 02:14:58 +02:00
Sign in to join this conversation.
No description provided.