From e7c179601570fd2608d3f92b015b8c2931f8360e Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Tue, 13 Jan 2026 23:00:03 +0100 Subject: [PATCH] JavaScript: faster randomness generation Fill entire buffers directly. --- dist-build/emscripten.sh | 18 +++++++++++ src/libsodium/randombytes/randombytes.c | 43 ++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/dist-build/emscripten.sh b/dist-build/emscripten.sh index f12d358e..651d058b 100755 --- a/dist-build/emscripten.sh +++ b/dist-build/emscripten.sh @@ -120,6 +120,20 @@ if [ "$DIST" = yes ]; then }; 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'); @@ -129,6 +143,10 @@ if [ "$DIST" = yes ]; then }; 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'; } diff --git a/src/libsodium/randombytes/randombytes.c b/src/libsodium/randombytes/randombytes.c index 85c24454..5ccb6703 100644 --- a/src/libsodium/randombytes/randombytes.c +++ b/src/libsodium/randombytes/randombytes.c @@ -65,6 +65,20 @@ javascript_stir(void) }; 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'); @@ -74,22 +88,41 @@ javascript_stir(void) }; 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'; } } } + if (Module.getRandomBytes === undefined) { + Module.getRandomBytes = function(ptr, size) { + var heapu8 = Module.HEAPU8; + for (var i = 0; i < size; i++) { + heapu8[ptr + i] = Module.getRandomValue() & 0xff; + } + }; + } }); } static void javascript_buf(void * const buf, const size_t size) { - unsigned char *p = (unsigned char *) buf; - size_t i; - - for (i = (size_t) 0U; i < size; i++) { - p[i] = (unsigned char) randombytes_random(); + if (size > (size_t) 0U) { + EM_ASM({ + if (Module.getRandomBytes === undefined) { + Module.getRandomBytes = function(ptr, size) { + var heapu8 = Module.HEAPU8; + for (var i = 0; i < size; i++) { + heapu8[ptr + i] = Module.getRandomValue() & 0xff; + } + }; + } + Module.getRandomBytes($0, $1); + }, buf, size); } } #endif