-1

I am trying to convert this into a node.js script. The issue I am running into, because window.crypto is not available in node.js, is that the Box Müller transform is not working and instead I am getting (barely) pseudo-random results from the else portion of the code below.

I tried using some of the answers from this question, but none of them are working. The node.js module crypto is not a 1:1 match for the browser method window.crypto, so I am struggling to adapt the Box Müller transform script from browser to node.js.

Specifically, I am looking for a node.js version of this portion of code:

if (crypto && typeof crypto.getRandomValues === 'function') { // What library can be used as an equivalent of crypto.getRandomValues?
    RAND_MAX = Math.pow(2, 32) - 1;
    array = new Uint32Array(1); // What is the node.js equivalent?
    random = function () {
        crypto.getRandomValues(array); // What is the node.js equivalent?

        return array[0] / RAND_MAX;
    };
} else {
    random = Math.random; // I don't want this
}

And more specifically, a way to accomplish the same thing that crypto.getRandomValues(array) in that code is doing.

Any help is greatly appreciated!

Dshiz
  • 3,099
  • 3
  • 26
  • 53
  • [lJavaScript Crypto Libraries](https://gist.github.com/jo/8619441) – Robert Oct 19 '20 at 00:02
  • Thanks - doing a quick search in SO, there really aren't many answers on how to apply any of those libraries in a similar way that the original code is doing: https://stackoverflow.com/search?q=window.crypto+node.js.. Any suggestion on how to apply any of those libraries for this purpose? – Dshiz Oct 19 '20 at 00:11
  • ok. but you have fallback. if you don't have crypto then you can use Math.random()....but you don't return value in else and you dont have bracket in Math.random function call – Robert Oct 19 '20 at 00:13
  • Yes, I am aware.. The fallback is giving terrible results. Note: the provided code is a snippet from the original SO answer here: https://stackoverflow.com/a/22080644/1551027. I have been trying to get that code working with a variety of answers I found on SO. I have been working with different libraries and adjusting the if statement as required, but nothing has been working for me. The if statement isn't the issue. – Dshiz Oct 19 '20 at 00:16
  • i made some research. and is not so easy to find something having sens. i don't know what you doing but if you don't find nothing what have sens you always can make small api point on node wich give you randome number ^^ with some delays but it can work. Just gener two numbers at once and cache them. it will have delay onlny on first action. – Robert Oct 19 '20 at 00:40
  • 1
    What is wrong with [crypto.randomBytes()[](https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback) or [crypto.randomFill()](https://nodejs.org/api/crypto.html#crypto_crypto_randomfill_buffer_offset_size_callback) ? – President James K. Polk Oct 19 '20 at 00:42
  • @PresidentJamesK.Polk `crypto.randomBytes()` doesn't give me a number like the original code does; it gives me an array of bytes that I'm not sure what to do with. I haven't tried `crypto.randomFill()` because I wasn't aware of that method. I will give it a try.. Update: `crypto.randomFill()` gives me an alphanumeric value that is not useable -- it needs to be a number. – Dshiz Oct 19 '20 at 00:46
  • 1
    `Uint32Array` is a _typed array_ and contains 32-bit unsigned integers with a value range between `0` and `RAND_MAX` (`4294967295`). The JavaScript code generates a `Uint32Array` with exactly _one_ element (i.e. 32 bits / 4 bytes), whose value is randomly generated with `crypto.getRandomValues()`. The NodeJS counterpart to `array[0]` could be e.g. `crypto.randomBytes(4).readUInt32BE()`. In both cases the division by `RAND_MAX` generates a random value between `0` and `1` (including both boundaries). – Topaco Oct 19 '20 at 06:58

1 Answers1

3

We can use crypto.randomBytes() to generate an array of 4 random bytes (32 bits), then divide by the maximum unsigned 32-bit integer size (2^32-1) of 0xffffffff to give us a random number between 0 and 1.

One could potentially use more than 4 bytes, e.g. perhaps use 8 bytes. This would, in principal be more secure.

const crypto = require("crypto");

function random() {
    const buffer = crypto.randomBytes(4);
    return buffer.readUInt32LE() / (0xffffffff); // Divide by maximum value of 32-bit unsigned int.
}

// Generate 10 numbers..
console.log(Array.from({ length: 10 }, (v,k) => random()));
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40