Emscripten: simplify randomness extraction

Use getentropy() for small buffers and WASI random_get for
larger buffers.
This commit is contained in:
Frank Denis
2026-09-22 10:39:29 +02:00
parent 57d44b9549
commit c960b3b0c6
2 changed files with 21 additions and 118 deletions
+1 -47
View File
@@ -156,49 +156,6 @@ if [ "$DIST" = yes ]; then
root = window;
}
}
if (typeof Module.getRandomValue === 'undefined') {
try {
var window_ = 'object' === typeof window ? window : self;
var crypto_ = typeof window_.crypto !== 'undefined' ? window_.crypto : window_.msCrypto;
var randomValuesStandard = function() {
var buf = new Uint32Array(1);
crypto_.getRandomValues(buf);
return buf[0] >>> 0;
};
randomValuesStandard();
Module.getRandomValue = randomValuesStandard;
Module.getRandomBytes = function(ptr, size) {
var heapu8 = Module.HEAPU8;
var chunk = 65536;
while (size > chunk) {
var buf = new Uint8Array(chunk);
crypto_.getRandomValues(buf);
heapu8.set(buf, ptr);
ptr += chunk;
size -= chunk;
}
var buf = new Uint8Array(size);
crypto_.getRandomValues(buf);
heapu8.set(buf, ptr);
};
} catch (e) {
try {
var crypto = require('crypto');
var randomValueNodeJS = function() {
var buf = crypto['randomBytes'](4);
return (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]) >>> 0;
};
randomValueNodeJS();
Module.getRandomValue = randomValueNodeJS;
Module.getRandomBytes = function(ptr, size) {
var buf = crypto['randomBytes'](size);
Module.HEAPU8.set(buf, ptr);
};
} catch (e) {
throw 'No secure random number generator found';
}
}
}
var _Module = Module;
Module.ready = new Promise(function(resolve, reject) {
var Module = _Module;
@@ -222,13 +179,10 @@ if [ "$DIST" = yes ]; then
return new Promise(function(resolve, reject) {
var Module = {};
Module.onAbort = reject;
Module.getRandomValue = _Module.getRandomValue;
Module.onRuntimeInitialized = function() {
Object.keys(_Module).forEach(function(k) {
if (k !== 'getRandomValue') {
delete _Module[k];
}
delete _Module[k];
});
Object.keys(Module).forEach(function(k) {
_Module[k] = Module[k];
+20 -71
View File
@@ -7,7 +7,8 @@
#include <sys/types.h>
#ifdef __EMSCRIPTEN__
# include <emscripten.h>
# include <unistd.h>
# include <wasi/api.h>
#endif
#include "core.h"
@@ -44,85 +45,33 @@ javascript_implementation_name(void)
static uint32_t
javascript_random(void)
{
return EM_ASM_INT_V({
return Module.getRandomValue();
});
uint32_t r;
if (getentropy(&r, sizeof r) != 0) {
sodium_misuse();
}
return r;
}
static void
javascript_stir(void)
{
EM_ASM({
if (Module.getRandomValue === undefined) {
try {
var window_ = 'object' === typeof window ? window : self;
var crypto_ = typeof window_.crypto !== 'undefined' ? window_.crypto : window_.msCrypto;
crypto_ = (crypto_ === undefined) ? crypto : crypto_;
var randomValuesStandard = function() {
var buf = new Uint32Array(1);
crypto_.getRandomValues(buf);
return buf[0] >>> 0;
};
randomValuesStandard();
Module.getRandomValue = randomValuesStandard;
Module.getRandomBytes = function(ptr, size) {
var heapu8 = HEAPU8;
var chunk = 65536;
while (size > chunk) {
var buf = new Uint8Array(chunk);
crypto_.getRandomValues(buf);
heapu8.set(buf, ptr);
ptr += chunk;
size -= chunk;
}
var buf = new Uint8Array(size);
crypto_.getRandomValues(buf);
heapu8.set(buf, ptr);
};
} catch (e) {
try {
var crypto = require('crypto');
var randomValueNodeJS = function() {
var buf = crypto['randomBytes'](4);
return (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]) >>> 0;
};
randomValueNodeJS();
Module.getRandomValue = randomValueNodeJS;
Module.getRandomBytes = function(ptr, size) {
var buf = crypto['randomBytes'](size);
HEAPU8.set(buf, ptr);
};
} catch (e) {
throw 'No secure random number generator found';
}
}
}
if (Module.getRandomBytes === undefined) {
Module.getRandomBytes = function(ptr, size) {
var heapu8 = HEAPU8;
for (var i = 0; i < size; i++) {
heapu8[ptr + i] = Module.getRandomValue() & 0xff;
}
};
}
});
(void) javascript_random();
}
static void
javascript_buf(void * const buf, const size_t size)
javascript_buf(void * const buf, size_t size)
{
if (size > (size_t) 0U) {
EM_ASM({
if (Module.getRandomBytes === undefined) {
Module.getRandomBytes = function(ptr, size) {
var heapu8 = HEAPU8;
for (var i = 0; i < size; i++) {
heapu8[ptr + i] = Module.getRandomValue() & 0xff;
}
};
}
Module.getRandomBytes($0, $1);
}, buf, size);
unsigned char *p = (unsigned char *) buf;
size_t chunk_size;
while (size > (size_t) 0U) {
chunk_size = size > 65536U ? 65536U : size;
if (__wasi_random_get(p, chunk_size) != 0) {
sodium_misuse();
}
p += chunk_size;
size -= chunk_size;
}
}
#endif