-1

I am using the below method to generate multiple unique random codes of 14 digits:

var randNum = Math.floor(Math.random() * timestamp * 100);
var number = randNum.toString().substr(0, 14);

Is this method secure for generating multiple unique codes? What are the odds to get a duplicate codes? Is there any other algorithm to generate random number with less time complexity in node js?

  • 5
    [`Math.random` is not defined/required to be cryptographically secure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random). – Alexander O'Mara Feb 15 '18 at 08:15
  • 1
    Uniqueness in the world (very low probability of dups) and cryptographically securely random (no predictability at all) are not the same thing. Which is it you care about? – jfriend00 Feb 15 '18 at 08:25
  • I would say this is not a duplicate, since this is about node.js, and not JS in the browser. – Anders Feb 15 '18 at 08:26
  • 1
    Since this is node.js, you may want to look at [`crypto.randomBytes()`](https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback). – jfriend00 Feb 15 '18 at 08:53
  • yes, it's fine as described. i would slice -14 (or whatever) to avoid the decimal. – dandavis Feb 15 '18 at 12:46
  • @AlexanderO'Mara Though I _think_ the Opera browser actually has a cryptographically secure `Math.random`. I wish other browsers would follow suit so implementation mistakes that end up using it when good randomness is required are less catastrophic. – forest Feb 15 '18 at 13:05
  • @forest: opera use the same thing as chrome. chrome's is a pretty good PRNG, you can read about it here: https://v8project.blogspot.com/2015/12/theres-mathrandom-and-then-theres.html afaik, there's no non-performance-constrained CSPRNG that would work across all the platforms browsers need to target. – dandavis Feb 15 '18 at 19:38
  • @dandavis Why would performance be an issue? ChaCha20 is fast enough that generating random bytes should certainly not be a bottleneck. – forest Feb 16 '18 at 03:22
  • @forest: that's a stream cipher, not a CSPRNG, which needs hardware entropy. crypto.getRandomBytes() has a data limit for this reason, and putting a limit on Math.random() could very well break existing code. FWIW, i see no need for a CSRNG in OP's description anyway, so a PRNG is fine... – dandavis Feb 16 '18 at 13:07
  • @dandavis A stream cipher can be used as a CSPRNG (e.g. as used by the Linux kernel, OpenBSD, CTR_DRBG, etc), and browsers have access to APIs for hardware entropy. All that is needed is 16 bytes of entropy once to generate an unlimited amount of randomness. While a CSPRNG may be unnecessary for OP, my point was just that it would help for the use cases where `Math.random` is abused (which is all too common). The fact that it uses a poor PRNG despite its ubiquitous abuse is a design flaw. – forest Feb 17 '18 at 04:07
  • I'm voting to close this question as off-topic because it cares only about the codes being unique. This is not an information security requirement. Such requirements would be instead about unguessable codes considering specific capabilities and resources of the attacker. And secure enough would be in this case that the resources needed to break these codes would be much higher than the (unknown) value of these codes. – Steffen Ullrich Feb 17 '18 at 14:00

1 Answers1

0

As the comments point out, you are probably doing something for which you should use a cryptographically secure (pseudo-)random number generator. The standard one for Node is crypto.randomBytes.

However, that doesn't actually answer your question. As it turns out, the actual answer involves somewhat complicated math but is known; see the Birthday Problem or Birthday Attack (for the scenario of somebody trying to cause a duplicate).

As a rough approximation, though, you can think of the chance of any duplicate as being about what the chance of a specific duplicate would be if there were half as many digits (half the bits entropy). That is, with 14 digits, you have 10^14 possible values, which is very close to 2^46.5. As such, you can say there at 46.5 bits of entropy in your random codes. There's only a 1/(2^46.5) chance of any single code matching any specific other single one.

However, when you generate a bunch of codes, the chances of a collision (duplicate) go way up, much faster than you think. By the time you've generated about 10,000,000 codes (10^7, or very close to 2^23.25), you will, on average, have about one duplicate (it's all statistics, of course, you might have no dupes, or one, or two, or twenty... but one would be the most likely number). This might seem like a large number, but if you're using this code for anything serious, it's way too small. You should be using much, much larger numbers. For unique IDs, 128 bits (roughly 3.4*10^38 possible values) is the standard size number to use. Don't try to generate that in base 10, of course; that's silly. It's only 16 completely random bytes, though.

CBHacking
  • 40,303
  • 3
  • 74
  • 98