Lokesh Harjani
Lokesh Harjani

Reputation: 119

How to generate 8 character unique string without checking if it exist in the database

I want to generate 1 million qr codes every day. every qr code should have random unique value. in order to achieve uniqueness i have two options as below

1)First option is to generate 8 characters alphanumeric random string and check if it is exist in database. if not exist then store in the database and if exist then retry gain.

The problem with this approach is that it takes around 45 minutes to generate 1 million unique alphanumeric strings because we have to check every time if generated alphanumeric string is present in the database or not.

2)Second option is to generate unique token by appending 6 characters alphanumeric string with time(hour+minute+second+date+month+year). with this option i am able to generate 1 million unique alphanumeric string within 5 minutes.

i am using this second option but the problem with this option is that the alphanumeric string generated from this is 15 characters long. i want to generate alphanumeric string with only 8 character long. if i use second option then timestamp itself takes 8 characters and string become easily guessable.

I want to know how to generate 8 characters random and unique alphanumeric string without checking if it exist in the database or not.

Upvotes: 1

Views: 3469

Answers (5)

Sampgun
Sampgun

Reputation: 2977

If someone still needs this, the most efficient way could be using SHA256 and Base64. I need it to generate temporary tokens with a 60 minutes duration. Here's an example using crypto-js to encrypt a counter, convert the result to Base64 and taking the first 8 characters:

import {SHA256, enc} from "crypto-js";

const tokens = Array.from({length: 1000000}}).map((_, i) => {
    return SHA256(`${i}`).toString(enc.Base64).substring(0, 8);
});

this produced 1 million unique codes (you can verify creating a Set from the array and check the size. It will match the Array length). If you have a strong machine you can try bigger numbers, but I guess this is fairly safe and performs fine. While I tried AES and it was a bit too heavy (very slow with 50k codes)

Upvotes: 1

John Hascall
John Hascall

Reputation: 9416

New plan.

Each day, take the numbers 000000..999999, shuffle them, base64 encode them (3 characters).

Take the number of days since your service started, as a six digit number, base64 encode that (3 chars). Good for a million days.

Note these numbers are unique and "random", but definitely not cryptographically secure at all.

EDIT some pseudo code:

int a[1000000];
int daysWeveBeenDoingThis;

for i from 0 to 999999 {
    a[i] = i
}
ShuffleArray(a);

function getNthTokenToday ( int n ) {
    String s = '';
    long x =
        (a[n] << 16L) + daysWeveBeenDoingThis);
    for c from 0 to 5 {
        v = (x >> (c*6)) & 63;
        b = 'a-zA-Z0-9/.'[v];
        s.append(b)(
    }
    return s;
}

Upvotes: 0

Akshay Borade
Akshay Borade

Reputation: 2472

Try this ...

token = SecureRandom.urlsafe_base64(6) # This will give you 8 char uniq string

Hope this will work for you.

Upvotes: 0

ElKamina
ElKamina

Reputation: 7817

You could use symmetric encryption (example AES) to create your unique ids.

First, create a unique secret key.

Second, initialize a counter.

For every new code you want to generate, encrypt the current counter value with your encryption key and use it. And increment the counter.

PS: Only minor weird thing is you want to use alphanumeric output. So use a 32 bit key and you will get 32 bit output. Now, convert that into 8 byte alphanumeric output.

Upvotes: 0

郑福真
郑福真

Reputation: 314

Using set structure is enough

def random_str(n):
    base = 'abcefghijklmnopqrstuvwxzy0123456789'
    return ''.join([base[ord(i) % len(base)] for i in os.urandom(n)])

s = set()
SIZE = 1000000
while len(s) < SIZE:
    s.add(random_str(5))

And, it takes about 5 seconds.

Sorry, I missing every day. Split the 8 characters to tow part: the first part(3 characters) meaning every day or other conditions, can store it in Mysql and query before generate once or using days since 1970 and change it to 36 based number. The seconds part 5 characters using the code above to generate unique keys.

Upvotes: 0

Related Questions