Search code examples
javascriptnode.jstypescriptcryptographycryptojs

Can crypto.getRandomValues(new Uint32Array(1))[0] / lim ever be negative?


Curious whether the expression crypto.getRandomValues(new Uint32Array(1))[0] / lim can ever be negative.

The code I'm converting puts a Math.abs wrapper around it, but some of us think that it's impossible for it to be negative, so just wanted to see what the rest of you think?

var lim = Math.pow(2, 32) - 1;
crypto.getRandomValues(new Uint32Array(1))[0] / lim);

This is the related question for more context: Converting getRandomValue.browser from cuid to Typescript?

The library has a getRandomValue() nodejs function that looks like this:

import * as crypto from "crypto"

var lim = Math.pow(2, 32) - 1;

export function getRandomValue () {
  return Math.abs(crypto.randomBytes(4)
    .readInt32BE(0) / lim)
}

I think for the browser, the Math.abs call was kept even though it seems it is not necessary, and quite possibly incorrect.


Solution

  • In this case, the use of Math.abs() would be wrong!

    The value in question, so says the declaration above, is UInt32 ... unsigned 32-bit integer.

    This simply means that the leftmost bit (most significant bit) is not to be interpreted as a sign-bit. This does not, however, prevent you from inadvertently using the value in some context which would assume that MSB=1 means "negative."

    Nonetheless, it would be wrong for you to use abs() because this would convert the entire bit-pattern, if it finds that MSB=1, into an entirely different bit-pattern. Since the MSB is simply "one of the 32 bits which comprises the value," it is dead-wrong to do anything to it which assumes that it's a sign-bit. And you also want to take care that it never gets displayed as a negative number, because it isn't. This quantity is 32 bits long, not 31+sign. Be sure it always looks that way.