React Native Synchronous Secure Random Number Generation
<p>I'm trying to generate keypairs in a React Native project. The key pair generation tool relies on the <code>crypto</code> module's random byte generation, which produces a buffer of a specified lengths with random byte values.</p>

<p>In order to use the <code>crypto</code> module within React Native, it has to be browserified, and the browserified random number generator looks like this:</p>

<p><a href="https://github.com/crypto-browserify/randombytes/blob/master/browser.js" rel="noreferrer">https://github.com/crypto-browserify/randombytes/blob/master/browser.js</a></p>

<p>Here's the key component:</p>

<pre><code>var crypto = global.crypto || global.msCrypto

if (crypto &amp;&amp; crypto.getRandomValues) {
  module.exports = randomBytes
} else {
  module.exports = oldBrowser
}
</code></pre>

<p>Indeed, when debugging the application with Chrome, everything works fine, but when running it on iOS's JavaScriptCore engine, the <code>oldBrowser</code> method gets called instead, throwing the following error:</p>

<blockquote>
  <p>secure random number generation not supported by this browser
  use chrome, FireFox or Internet Explorer 11</p>
</blockquote>

<p>Thus I'm trying to find a replacement for the random bytes generation. One module I found is this one:</p>

<p><a href="https://www.npmjs.com/package/react-native-randombytes" rel="noreferrer">https://www.npmjs.com/package/react-native-randombytes</a></p>

<p>It uses the device's native libraries to generate a random number, and exposes it to React Native through their Obj-C/JS interface. It should be noted that this method only works on iOS, and the library's author doesn't have an Android solution yet, but that's an issue for another time.</p>

<p>This method works, in that it can generate random bytes, but it has one major drawback. React only supports asynchronous interfacing between Objective-C and JavaScript, which means that this method returns its results asynchronously. The original <code>randomBytes</code> method is synchronous, and pretty much every SDK out there that relies on it uses it synchronously. So if we were to go with the async version, all the SDKs would have to be rewritten for it, including all dependencies that rely on methods that used to be synchronous and now would no longer be.</p>

<p>Thus I'm trying to find a way to make the asynchronous native random number generator work synchronously. There are several node packages that do that, the most prominent one of them being <code>deasync</code>, but <code>deasync</code> relies on some core Node modules that cannot be browserified, so the synchronous version doesn't work.</p>

<p>Alternatively, I've tried wrapping it in a method that would set a semaphore, call the async generator, and wait in a while loop for the semaphore's value to change. That attempt failed because the while loop was blocking the callback from ever executing. Here's an approximation of my attempts, where the call to the async method has been replaced with a <code>setTimeout</code>, and the random number to be returned is a four, as determined by a fair dice roll.</p>

<pre><code>function testSynchronicity() {
  var isDone = false;
  setTimeout(function() {
    isDone = true;
  }, 1000); // set isDone to true after a second

  while (!isDone) {
    // do nothing
  }
  return 4;
};
</code></pre>

<p>As this wasn't working, I figured I would try a completely different random number generator entirely, without the native-code-relying <code>react-native-randombytes</code> module and went with this one for JavaScript: </p>

<p><a href="https://github.com/skeeto/rng-js" rel="noreferrer">https://github.com/skeeto/rng-js</a></p>

<p>It worked fine within Node itself, but after browserifying it and trying to run the first example within React Native, it threw an error saying that the main object was not a constructor. Here's what the example looks like:</p>

<pre><code>var RNG = require('./rng_react'); // rng_react is rng-js browserified
var rng = new RNG();
var randomValue = rng.random(0, 255, false);
</code></pre>

<p>So at this point, I'm at a bit of a loss, and would appreciate any help. Thanks!</p>

<p><strong>EDIT</strong>: If all else fails, there's this, but I think it would pretty much beat the purpose of the question. <a href="https://github.com/bitpay/bitcore-lib/blob/master/lib/crypto/random.js#L37" rel="noreferrer">https://github.com/bitpay/bitcore-lib/blob/master/lib/crypto/random.js#L37</a></p>