PiTheNumber
PiTheNumber

Reputation: 23542

Generate shorter public id

I am looking for a way to generate public ids for my objects (like a facebook uid). The id should be unique and the user should not be able to guess it (or the next one).

Right now I am using this:

sha1('a fixed random string' . $this->getId())

The problem is that sha1 generates very long strings (40 chars) and I would like it to be shorter. I thought about using MD5 but it's known to be not save because you can create collisions. Is this really a problem in my case?

What alternatives do I have?

Upvotes: 2

Views: 776

Answers (5)

PiTheNumber
PiTheNumber

Reputation: 23542

I made some tests to see how long the id will be using different hash functions. I also used convBase to convert from 0-9a-z to 0-9a-zA-Z as suggested:

$i = mt_rand(1, PHP_INT_MAX);
sha1($i):           40 322c73c44958e4219fd6679aead094192cb672fe
convBase(sha1($i)): 34 1JHrlXObHSVMcbn2bHRBCBIRD3RVKQHMQzg
md5($i):            32 7b09f8cd76be44403b90e971a5a61e6c
convBase(md5($i)):  28 5bgdGpBZekbb3PQlILrSKMtHC24A
$i:                  9 107300785
convBase($i):        5 7gdPP

So sha1 is very long even if converted to the other base. Also I am still not sure if MD5 is secure. Anyway, with 28 characters it is still kind of long if you want to post it in an URL on twitter: http://mydomainsux.com/invite/5bgdGpBZekbb3PQlILrSKMtHC24A

The shortest solution with convBase($i) has the problem of not being unique. You would have to check for that manually. Still, I think this is the way to go here because if you use a hash there could also be a natural collusion so you have to check anyway.

I read that you can pre generate the id's in a table and just pick one whenever you need one. This way you do not have to test for uniqueness every time.

Upvotes: 0

Alex
Alex

Reputation: 34958

Use a random integer and than perform a base convert. The idea is that you use a target charset of many character such as A-Z, a-z and 0-9. By this your number can be encoded in a very short string.

For the simple version that users 0-9 and a-z you can use the PHP function base_convert: (http://codepad.org/9craDgbt)

echo base_convert ( 123456789132465798132 , 10 , 36 );

gives you

c5m8nqw9ps

If you want to have it even shorter, have a look at the function "convBase" in the comments of http://php.net/manual/de/function.base-convert.php. By increasing the number of characters in the target charset, the result gets shorter.

convBase($randomInt,'0123456789','0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');

Upvotes: 1

Savas Vedova
Savas Vedova

Reputation: 5692

If you are going to store the ids in a database then you can go for uniqid. If you're going to use normal id's (those auto_increments) in database and just want to use a representative id create a function with some math calculations inside :)

Upvotes: 1

OptimusCrime
OptimusCrime

Reputation: 14863

Why would you hash unique values like this? I think it's much better to just use the unique integer like it is.

Although, it you really want to hash it, take a look at this: http://www.php.net/manual/en/function.hash-algos.php , that is the complete list of hashing-functions available. Check to see what is installed on your server.

Upvotes: 0

Aurimas Ličkus
Aurimas Ličkus

Reputation: 10074

If you use strong salt (random string) it is not big problem of MD5 collisions.

Upvotes: 1

Related Questions