Reputation: 23542
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
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
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
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
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
Reputation: 10074
If you use strong salt (random string) it is not big problem of MD5 collisions.
Upvotes: 1