Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating Strong Unique User ID's w/PHP & MySQL

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 prefer to hear what others might suggest.
  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 :) -------------------------------

like image 833
brack Avatar asked Aug 06 '09 18:08

brack


3 Answers

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.

like image 129
willoller Avatar answered Oct 10 '22 03:10

willoller


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 ?

like image 34
Pascal MARTIN Avatar answered Oct 10 '22 04:10

Pascal MARTIN


I wrote this class that gives you an unique id of 24 chars, compatible with the id field of MongoDB (and using the same logic to construct it). Might be useful in the future.

<?php
/**
 * Generator for Mongo-like ObjectIds in pure PHP
 * Author: Mauricio Piacentini
 *
 * Inspired by https://github.com/justaprogrammer/ObjectId.js
 *
 */

class ObjectIdFactory
{   
    private $_datetime = null;
    private $_machine = null;
    private $_pid = null;
    private $_increment = null;

    public function __construct()
    {
        $this->_machine = str_pad(dechex(rand(0, 16777215)), 6, "0", STR_PAD_LEFT);
        $this->_pid = str_pad(dechex(rand(0, 32767)), 4, "0", STR_PAD_LEFT);
        $this->_increment = rand(0, 16777215);

        //We need a DateTime object to get timestamps, cache it
        $this->_datetime = new DateTime();
    }

    public function getNewId($forcedincrement = null)
    {
        if (is_null($forcedincrement)) {
            $this->_increment++;
            if ($this->_increment > 0xffffff) {
                $this->_increment = 0;
            }
        } else {
            $this->_increment = $forcedincrement;
        }
        $timestamp = $this->_datetime->getTimestamp();

        $timestamp_final = str_pad(dechex($timestamp), 8, "0", STR_PAD_LEFT);
        $increment_final = str_pad(dechex($this->_increment), 6, "0", STR_PAD_LEFT);
        return $timestamp_final . $this->_machine . $this->_pid . $increment_final;
    }

}

https://github.com/piacentini/ObjectId.php

like image 32
piacentini Avatar answered Oct 10 '22 04:10

piacentini