Node.js - How to generate random numbers in a specific range using crypto.randomBytes

How can I generate random numbers in a specific range using crypto.randomBytes?

I want to be able to generate a random number like this:

console.log(random(55, 956)); // where 55 is minimum and 956 is maximum 

and I can use crypto.randomBytes only inside random to generate a random number for this range.

I know how to convert generated bytes from randomBytes to hex or decimal, but I cannot figure out how to mathematically get a random number in a certain range from random bytes.

+5
source share
3 answers

Thanks to the answer from @Mustafamg and the huge help from @CodesInChaos, I was able to solve this problem. I made some changes and increased the range to a maximum of 256 ^ 6-1 or 281,474,976,710,655. The range can be increased more, but you need to use an additional library for large integers, because 256 ^ 7-1 is outside the limits of Number.MAX_SAFE_INTEGER.

If anyone has the same problem, feel free to use it.

 var crypto = require('crypto'); /* Generating random numbers in specific range using crypto.randomBytes from crypto library Maximum available range is 281474976710655 or 256^6-1 Maximum number for range must be equal or less than Number.MAX_SAFE_INTEGER (usually 9007199254740991) Usage examples: cryptoRandomNumber(0, 350); cryptoRandomNumber(556, 1250425); cryptoRandomNumber(0, 281474976710655); cryptoRandomNumber((Number.MAX_SAFE_INTEGER-281474976710655), Number.MAX_SAFE_INTEGER); Tested and working on 64bit Windows and Unix operation systems. */ function cryptoRandomNumber(minimum, maximum){ var distance = maximum-minimum; if(minimum>=maximum){ console.log('Minimum number should be less than maximum'); return false; } else if(distance>281474976710655){ console.log('You can not get all possible random numbers if range is greater than 256^6-1'); return false; } else if(maximum>Number.MAX_SAFE_INTEGER){ console.log('Maximum number should be safe integer limit'); return false; } else { var maxBytes = 6; var maxDec = 281474976710656; // To avoid huge mathematical operations and increase function performance for small ranges, you can uncomment following script /* if(distance<256){ maxBytes = 1; maxDec = 256; } else if(distance<65536){ maxBytes = 2; maxDec = 65536; } else if(distance<16777216){ maxBytes = 3; maxDec = 16777216; } else if(distance<4294967296){ maxBytes = 4; maxDec = 4294967296; } else if(distance<1099511627776){ maxBytes = 4; maxDec = 1099511627776; } */ var randbytes = parseInt(crypto.randomBytes(maxBytes).toString('hex'), 16); var result = Math.floor(randbytes/maxDec*(maximum-minimum+1)+minimum); if(result>maximum){ result = maximum; } return result; } } 

This works fine so far, and you can use it as a really good random number generator, but I strongly recommend against using this feature for any cryptographic services. If you do, use it at your own risk.

All comments, recommendations and critics are welcome!

+2
source

To generate a random number in a specific range, you can use the following equation

 Math.random() * (high - low) + low 

But you want to use crypto.randomBytes instead of Math.random (), this function returns a buffer with randomly generated bytes. In turn, you need to convert the result of this function from bytes to decimal. this can be done using the biguint-format package. To install this package, simply use the following command:

 npm install biguint-format --save 

Now you need to convert the result of crypto.randomBytes to decimal, you can do it like this:

 var x= crypto.randomBytes(1); return format(x, 'dec'); 

Now you can create your random function, which will be as follows:

 var crypto = require('crypto'), format = require('biguint-format'); function randomC (qty) { var x= crypto.randomBytes(qty); return format(x, 'dec'); } function random (low, high) { return randomC(4)/Math.pow(2,4*8-1) * (high - low) + low; } console.log(random(50,1000)); 
+6
source

To generate numbers in the range [55 .. 956], you first generate a random number in the range [0 .. 901], where 901 = 956 - 55. Then add 55 to the number that you just generated.

To generate a number in the range [0 .. 901], select two random bytes and fill in 6 bits. This will give you a 10-bit random number in the range [0 .. 1023]. If this number is <= 901, then you are done. If it is greater than 901, drop it and get two more random bytes. Make no attempt to use MOD to get a number in the right range, which will distort the output, making it nonrandom.

ETA: to reduce the chance of rejecting the generated number.

Since we take two bytes from the RNG, we get a number in the range [0 .. 65535]. Now 65535 MOD 902 is 591. Therefore, if our two-byte random number is less (65535 - 591), that is, less than 64944, we can safely use the MOD operator, since every number in the range [0 .. 901] is currently equally likely . Any two-byte number> = 64944 will still have to be thrown away, since using this would distort the way out of the random. Previously, the chances of rejecting the number were (1024 - 901) / 1024 = 12%. Now the odds of rejection (65535 - 64944) / 65535 = 1%. We are much less likely to reject a randomly generated number.

 running <- true while running num <- two byte random if (num < 64944) result <- num MOD 902 running <- false endif endwhile return result + 55 
+4
source

Source: https://habr.com/ru/post/1235538/


All Articles