Skip to content

Commit

Permalink
[emscripten]: use javascript for random generation (#2750)
Browse files Browse the repository at this point in the history
* feat(wasm): use javascript for random generation
* feat(wasm): fix per review
* add link to libsodium
  • Loading branch information
Milerius committed Nov 21, 2022
1 parent 69b2da9 commit d3c2eee
Showing 1 changed file with 70 additions and 6 deletions.
76 changes: 70 additions & 6 deletions wasm/src/Random.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,84 @@
// file LICENSE at the root of the source code distribution tree.
//

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <random>
#include <emscripten.h>

// clang-format off
static uint32_t
javascript_random(void)
{
return EM_ASM_INT_V({
return Module.getRandomValue();
});
}

// https://github.com/jedisct1/libsodium/blob/master/src/libsodium/randombytes/randombytes.c#L53
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;
var randomValuesStandard = function() {
var buf = new Uint32Array(1);
crypto_.getRandomValues(buf);
return buf[0] >>> 0;
};
randomValuesStandard();
Module.getRandomValue = randomValuesStandard;
} 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;
} catch (e) {
throw 'No secure random number generator found';
}
}
}
});
}


static void
randombytes_init_if_needed(void)
{
static bool initialized = false;
if (!initialized) {
javascript_stir();
initialized = true;
}
}

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) javascript_random();
}
}
// clang-format on

extern "C" {
uint32_t random32(void) {
std::mt19937 rng(std::random_device{}());
return rng();
randombytes_init_if_needed();
return javascript_random();
}

void random_buffer(uint8_t* buf, size_t len) {
std::mt19937 rng(std::random_device{}());
std::generate_n(buf, len, [&rng]() -> uint8_t { return rng() & 0x000000ff; });
randombytes_init_if_needed();
javascript_buf(buf, len);
return;
}

Expand Down

0 comments on commit d3c2eee

Please sign in to comment.