2

My Boss asked me this today. I am not a math major. He needs to generate 50 billion non-sequential non-duplicate (no collisions) cryptographically secure random numbers. I work in GO. Any ideas?

LostinMath
  • 21
  • 1

1 Answers1

3

I had to do the exact same thing for unique product identifier codes. In my case they needed to be random looking, not cryptographically secure, so I had more room to work with. I still went with a cryptographic method since that is what I was familiar with.

In your case, you are looking for just under $2^{36}$ values, for which all values are unique, and where guessing the next number in a sequence is infeasible (at least 50 billion possible choices), even when given all previous values.

For this the easiest option is a block cipher with a block size of at least 37-bits performing the encryption operation on an incrementing counter. DES, Blowfish, AES, and others all meet the criteria, the difference being key size, ciphertext size, and hardware support. Since 64-bit Go supports AES hardware acceleration, it is probably your best option.

Simply generate a cryptographically random key, start with an all 0 block, encrypt the block and save the output, increment the input block by treating it as 2 64-bit integers and incrementing the 2nd one (+1), repeat steps as needed until all values are generated. You can generate quadrillions of unique and cryptographically pseudorandom 128-bit values.

Richie Frame
  • 13,097
  • 1
  • 25
  • 42
  • You mean a block size of at least 37 bits right? Btw. an other reason to pick a larger block size (like 128 bits AES) would be to make it harder to guess one of your 50 billion numbers. Not sure if needed for this application though. – Guut Boy Jun 30 '15 at 08:34
  • @GuutBoy yes 37-bits, corrected – Richie Frame Jun 30 '15 at 11:04
  • @GuutBoy Not just to make it harder to guess one of the numbers, but to prevent duplicates during the creation process. If a 64-bit key was used, there's at least a 75% chance that will happen. Using a 128-bit key reduces the odds to less than $10^{-15}$. This is basically a birthday attack. – dbush Jun 30 '15 at 12:34
  • That doesnt sound right to me. Note in the above scheme we only pick a single random AES key. Encrypting two distinct plaintext blocks should always yield distinct encryptions using the same key. Otherwise there is no way to decrypt. Thus encrypting an incrementing counter should precisely ensure you that there will not be duplicates. The only problem would be if the block is not large enough to hold the entire counter. However, here we only need generate around $2^{36}$ numbers. I.e., a 128-bit AES block should be more than sufficient. – Guut Boy Jun 30 '15 at 12:45
  • You're right, there should be a 1:1 mapping between plaintexts and ciphertexts for a given key. I got mixed up thinking about hash functions. – dbush Jun 30 '15 at 13:07
  • If you want to do this and get closer to that 37 bit block size while using a pre-existing algorithm then know the Simon and Speck families include a 48 bit block sized version. – Thomas M. DuBuisson Jun 30 '15 at 14:31