views:

665

answers:

4

Ahoy Stack Overflow! This be mai first post...

I'm attempting to identify users with a salted unique public key.

  1. Algorithm - Should I use uniqid(), sha256, sha512, something else? All hashes will be salted. NIST recommended SHA256, but I like recommendations from geeks/scientists like me.
  2. Generation - Does hash(SALT + AUTO_INCREMENT_PK + CREATED_TIMESTAMP) suffice? More entropy?
    • I'd use email, as it is unique for each user, however the user can modify their email address. I was also considering storing signup_email so that hashes would not have to be re-calculated.
  3. MySQL Storage - Currently, our ID's are INT(255) auto_increment primary key's. As stated earlier, potentially hundreds of millions of keys. Depending on the crypto algo, I should have a fixed-size ID. Can I keep INT(255) or should I use CHAR(n)?

---------------------- Thanks for reading :) -------------------------------

+3  A: 

One thing: If you don't trust the users with their IDs, sending them over GET or POST will not work; those are all visible to motivated users.


I would use SHA256 using a salt.counter.time string, and use the output to generate GUIDs for the actual id. This would minimize the possibility for collisions.

You will have to use CHAR for MySQL to store GUIDs.

See the comments at http://us2.php.net/manual/en/function.uniqid.php for more in-depth info. AFAIK GUID is not part of the PHP core so you have to fake it a bit.

willoller
Hashing is not necessary. Actually hashing functions don’t create unique values.
Gumbo
@Gumbo - Not technically, but using a quality hash like Rijndal with high-quality entropy input can be used to produce a hash with *astronomically* low collisions approaching zero.
willoller
This pretty much answer's my question, as I was curious to whether or not I'd need char or if I could keep INT. As will also mentioned, astronomically low collision chance is OK with me, as I think I will have enough entropy. I'll look into salt.counter.time as well.If I produce hashes while maintaining a low collision rate, would the potential exist to still use MySQL's INT(255) as the data type?
brack
You could store the GUIDs in a lookup table, or you could use an INT for your PK and keep the GUID in a second column. It's possible that would give you improved performance since you would be using an INT to do your JOINs and INDEXes, but I'm not sure.
willoller
Yes, my user table currently uses an incremental INT for the PK, and I was going to add another UID column. Perhaps I should still always reference the User ID in the db as an int, and only use the UID for when it is exposed.
brack
@willoller: Using a real UID function will give you a collision probability of zero.
Gumbo
+3  A: 

If you are using user id as the way to allow a user to do anything with your service, if one user "guesses" the user id of another one, he'll be able to do whatever he wants with that one's account ?

You do not have any kind of other password or anything to go along that ?


Well, in that case, you need something quite unique, don't you ;-)
(Hoping I understood the question well -- but that might not be the case -- sorry, if it isn't)

What do you think of using Globally Unique Identifier (like, for instance, 61350955-9755-4AF3-8C19-6DBC42CA69E2) for your users ?
For an example of how they look like, take a look at http://createguid.com/


As a sidenote, that GUID is quite long ; which means lots of bytes in your DB, if you have millions users... So, it probably shouldn't be used as any kind of primary/foreign key.

What about using the smallest possible integer (that fits the number of users you'll have) as primary/foreign key, as that one will be duplicated in many places of the application ; and only have the "long user id" stored only once, in your user table ?

Pascal MARTIN
Passwords exist for users, yes... I think I may have gone a little too in depth... Basically I just need a safe way to keep the user somewhat secure, but also just to identify the user in the db logic. I'm OK with people seeing the user's public ID, as their DB-level id is hidden and unique. They also won't have access to the web service, and will need to be authenticated to access any functions that would be hazardous.
brack
Additionally, the intent of this ID is to be stored as you mentioned -- I wish to only store the long user id in the user core table, and reference it via other user tables. I am using an incremental int id, but I want to keep that hidden and never expose it outside of PHP and MySQL.Thanks
brack
A: 

Have you looked into using a UUID?

A quick google search yields some good resources/links.

Peter Bailey
A: 

Personally I use md5(uniqid(mt_rand(), true)) which will create 32 character identifier (a 128 bit hex number) that is extremely difficult to predict.

Bakhtiyor