Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate a pseudo random 6 character string from an integer

Tags:

php

base

hash

I am trying to resolve the following problem via PHP. The aim is to generate a unique 6-character string based on an integer seed and containing a predefined range of characters. The second requirement is that the string must appear random (so if code 1 were 100000, it is not acceptable for code 2 to be 100001, and 3 100002)

The range of characters is:

  • Uppercase A-Z excluding: B, I, O, S and Z
  • 0-9 excluding: 0, 1, 2, 5, 8

So that would be a total of 26 characters if I am not mistaken. My first idea would to be encoding from base 10 to base 24 starting at number 7962624. So do 7962624 + seed, and then base24 encode that number.

This gives me the characters 0-N. If I replace the resulting string in the following fashion, I then meet the first criteria:

B=P, I=Q, 0=R, 1=T, 2=U, 5=V, 8=W

So at this point, my codes will look something like this:

1=TRRRR, 2=TRRRT, 3=TRRRU

So my question to you gurus is: How can I make a method that behaves consistently (so the return string for a given integer is always the same) and meets the 2 requirements above? I have spent 2 full days on this now and short of dumping 700,000,000 codes into a database and retrieving them randomly I'm all out of ideas.

Stephen

like image 471
Stephen Groom Avatar asked Oct 03 '13 14:10

Stephen Groom


1 Answers

You get a reasonably random looking sequence if you take your input sequence 1,2,3... and apply a linear map modulo a prime number. The number of unique codes is limited to the prime number so you should choose a large one. The resulting codes will be unique as long as you choose a multiplier that's not divisible by the prime.

Here's an example: With 6 characters you can make 266=308915776 unique strings, so a suitable prime number could be 308915753. This function therefore will generate over 300.000.000 unique codes:

function encode($num) {
    $scrambled = (240049382*$num + 37043083) % 308915753;
    return base_convert($scrambled, 10, 26);
}

Make sure that you run this on 64bit PHP though, otherwise the multiplication will overflow. On 32bit you'll have to use bcmath. The codes generated for the numbers 1 through 9 are:

n89a2d
hdh4jo
biopb9
5o6k2k
3eek5
k8m9aj
ee4424
8jbojf
2ojjb0

All that's left is filling in the initial 0s that are sometimes missing and replacing the letters and numbers so that none of the forbidden characters are produced.

As you can see, there's no obvious pattern, but someone with some time on their hands, enough motivation and with access to a few of this codes will be able to find out what's going on. A safer alternative is using an encryption algorithm with a small block size, such as Skip32.

like image 159
Joni Avatar answered Nov 04 '22 03:11

Joni