Reputation: 119
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
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
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
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
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