I'm talking about Online activation. My current workflow is:

  1. User pays via paypal (without registration)
  2. Paypal performs a request to my API.
  3. My API returns a serial key to the user.
  4. Then the user is able to register using this serial key.

Is a "pay to register then use" and not a "register then pay to use".

So the question is:

  • Should I generate (let's say 100) keys and store them in DB then pick the first one available when someone pays via paypal? Isn't this vulnerable to "guess" attacks?
  • Should I generate 1 random key each time a user pays via paypal? Can't this approach generate 2 equal keys? I mean I have no info from the user except what paypal tells me so I should somehow use a random function OR loop the entire table comparing the serial keys.
  • These "keys" don't function like usernames, do they? If you tie keys to a specific account using an email, username, phone number, session cookie, or whatever then it doesn't matter if two different users are issued the same registration key. It can only make keys harder to predict if different user's keys are generated randomly independently of each other. Mar 14, 2020 at 17:24

2 Answers 2


Randomness and uniqueness are different concepts. Few random values from a large entropy space are generally all different but there is no guarantee on that. If you need both, I would split the key in two parts: one would be a simple sequence (uniqueness is guaranteed) and the latter would be produced by a random generator.

The size of those parts depends on your requirements: estimated number of keys give the first part, robustness to brute force attacks give the second one.

If the size of key must be limited and if you still want high brute force resistance, you will have to only use a random value and store all produced ones. Then when you need a new one, you just loop on random values until you find a unique one.

IHMO producing a bunch in advance or one at a time is just an implementation detail. If you realize that producing a new key could take too much time and lead to poor performances, it can make sense to always have a small number of keys pre-calculated in the application. You could use a background thread feeding a queue here...

  • That's a great answer, thank you. I think I will stick with the 2 part keys you explained. Pre-generating only the first part of the key to be sure they are unique and when a user pays, it will pick one that is available and generate a random value for it. So now even if someone "guesses" a key, it would have to be active without being used and also that someone would have to guess the random part as well. Mar 14, 2020 at 14:31

You could use a UUID4 generator as your serial number. For most practical purposes, it's guaranteed to be unique. Most programming languages has a generator library. If you want want to eliminate chances of uniqueness, you can have an endpoint which quickly checks against a bloom filter for uniqueness. Bloom filters guarantee that element is not present in set, which is perfect for your use-case and uses O(1) space. If element doesn't exist, then it updates bloom filter to avoid future collision.

About UUID, from wikipedia: When generated according to the standard methods, UUIDs are for practical purposes unique. Their uniqueness does not depend on a central registration authority or coordination between the parties generating them, unlike most other numbering schemes. While the probability that a UUID will be duplicated is not zero, it is close enough to zero to be negligible.

About bloom filter: A Bloom filter is a data structure designed to tell you, rapidly and memory-efficiently, whether an element is present in a set. The price paid for this efficiency is that a Bloom filter is a probabilistic data structure: it tells us that the element either definitely is not in the set or may be in the set.

  • UUIDs are a bad idea. Don't count on any library to generate unpredictable ones. If it uses the MAC address then that's going to leave part of the UUID static which just makes it easier to guess. Revealing a MAC address or timestamp also leaks information that may be exploitable somewhere. If the library uses random numbers, it's likely they weren't securely generated. You're always better pulling a 128-bit random number from /dev/urandom (etc.) if security might be a factor. Best case scenario UUIDs get you less than 123 bits of randomness. Mar 14, 2020 at 17:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .