# Situation

I need to generate unique 16-digit decimal values in NodeJS API or C++ Addon.

It's used internally in my organization (gift card id). And performance doesn't matter as it's generated non-realtime.

I've searched for some options, but unsure about their safety. If there's better way to do it, please let me know.

## Option 1. Use crypto.randomInt

Generate Integer Between 0 and 9, 16 Times.

The documentation says it avoids modulo bias. But I'm not sure it's unbiased when used 16 consecutive times.

## Option 2. Random Hash Value + Modulo 10

1. Create SHA-256 hash value from microsecond precision time.
2. Create UInt16Array, do % 10 on Each Element.

I guess this will have modulo bias. Is there any API or technique to safely chop SHA-256 value into 16 digit decimal number?

• If you generate more than one 16-digit uniformly random values, there is no assurance they are unique. For 20 million values generated, the probability of a collision is ≈2%, and about quadruples when one doubles the number of values generated. That dooms the methods in the question. This calls for a keyed permutation of integers in $[0,10^{16})$, a classical application of Format Preserving Encryption. We have several questions about that.
– fgrieu
Dec 26, 2022 at 17:35
• It might be worth think in terms of a 15-digit number and a checksum digit - you get more random collisions, but reduces that chances of a mistyped number Dec 26, 2022 at 19:06
• We are not about answering programming questions. Why not split the problem into two parts: creating the protocol to create the numbers and the implementation of the chosen protocol? If you edit out the NodeJS & C++ part it is more likely to get answers here instead of close votes. Dec 26, 2022 at 20:35

The questions looks to me like an XY problem.

1. It is not clear why the gift card numbers need to consist of 16 digits. Amazon has 1.5 million employees, McDonald's has 1.9 million. Even for such huge companies 7 digits would be sufficient. Even if you add a checksum digit, 16 digits would not be necessary.

2. For the given purpose, generation of gift card numbers, a random generator is not necessary. We usually use random generator: A) When we cannot keep the whole registry of possible numbers, e.g. when it would require much CPU load, or much storage, or long response time; B) If we want that many parties can generate numbers independently and keep the probability of collisions low. In your case you have a full control of all numbers to be generated. The numbers can be generated at once, by a single application.

That's why I'd suggest following approach:

• Generate a list of numbers of git cards starting from 1 to the number of employees.
• Shuffle this list.

Then every employee number will be associated with some randomly looking gift card number.

If you want to keep gift card numbers over years unchanged and not generate them every year, and if you expect that your company is growing and new employees will need gift cards, and you want to avoid correlation of higher numbers with new employees, then yes, random generator would be helpful.

In such case you can take the number of employees, multiply it by 10 or by 100, and generate numbers in this range. For instance, if there are 10 000 employees in your company, you can take a range 1 to 1 000 000 and generate numbers randomly and assign them to employees. Checking of collisions will be easy, because keeping an array of let say 1 000 000 elements in memory is simple and fast. In case of collision you just generate a new number, until there is no collision, or add some fixed value like 1, until there is no collision.

When later on new cards will be needed, there will be sufficient "wholes" in this range for new numbers.

A function can look as follows:

next_card_number = Math.floor( Math.random() * N )


N - the highest gift card number. For instance, if there are 10 000 employees, you can use 999 999 as the highest gift card number.