2009-08-06 49 views
5

Ahoy Stack Overflow! Esta debe ser la primera publicación ...Generando ID de usuario único fuerte con PHP y MySQL

Estoy intentando identificar a los usuarios con una clave pública única salada.

  1. Algoritmo - ¿Debo usar uniqid(), SHA256, SHA512, algo más? Todos los hash serán salados. NIST recomendó SHA256, pero prefiero escuchar lo que otros podrían sugerir.
  2. Generación - ¿Tiene (+ AUTO_INCREMENT_PK + CREATED_TIMESTAMP SAL) basta de hash? Más entropía?
    • Utilizaría el correo electrónico, ya que es único para cada usuario, sin embargo, el usuario puede modificar su dirección de correo electrónico. También estaba considerando almacenar signup_email para que los hash no tengan que volver a calcularse.
  3. de almacenamiento de MySQL - En la actualidad, de nuestros identificación son INT (255) auto_increment la clave primaria de. Como se dijo anteriormente, potencialmente cientos de millones de claves. Dependiendo del crypto algo, debería tener una ID de tamaño fijo. ¿Puedo mantener INT (255) o debería usar CHAR (n)?

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

+0

supongo un objetivo complementario: es la velocidad total de este tipo de sistema que va a ser mejor que el uso de números enteros incrementales, y es que vale la velocidad para obtener seguridad adicional? ¿Estoy en lo cierto al pensar que INT puede almacenar hexadecimal de manera eficiente? según la sugerencia del will, creo que probaré sha256. – brack

Respuesta

5

Una cosa: Si usted no confía en los usuarios con sus documentos de identidad, enviarlos a través de GET o POST no funcionarán; todos son visibles para los usuarios motivados.


me gustaría utilizar SHA256 mediante una cadena de salt.counter.time, y utilizar la salida para generar GUID para la identificación real. Esto minimizaría la posibilidad de colisiones.

Deberá usar CHAR para MySQL para almacenar GUID.

Consulte los comentarios en http://us2.php.net/manual/en/function.uniqid.php para obtener información más detallada. AFAIK GUID no es parte del núcleo PHP, así que tienes que fingir un poco.

+0

Hashing no es necesario. En realidad, las funciones hash no crean valores únicos. – Gumbo

+0

@Gumbo - No técnicamente, pero usando un hash de calidad como Rijndal con entrada de entropía de alta calidad se puede usar para producir un hash con * astronómicamente * bajas colisiones que se aproximan a cero. – willoller

+0

Esta casi respuesta es mi pregunta, ya que tenía curiosidad por saber si necesitaría char o si podría mantener INT. Como también se mencionó, la posibilidad de colisión astronómicamente baja está bien conmigo, ya que creo que tendré suficiente entropía. Voy a investigar salt.unter.time también. Si produzco hashes mientras mantengo una baja tasa de colisión, ¿existiría la posibilidad de seguir usando INT de MySQL (255) como el tipo de datos? – brack

3

Si usa la identificación del usuario como forma de permitir que un usuario haga algo con su servicio, si un usuario "adivina" la identificación de usuario de otra, podrá hacer lo que quiera con la de ese cuenta?

¿No tiene ningún otro tipo de contraseña o algo así?


Bueno, en ese caso, se necesita algo bastante único, ¿verdad ;-)
(Esperando entendí bien la pregunta - pero eso podría no ser el caso - lo siento, si no es)

¿Qué piensas del uso de Globally Unique Identifier (como, por ejemplo, 61350955-9755-4AF3-8C19-6DBC42CA69E2) para tus usuarios?
Para un ejemplo de cómo se ven, echar un vistazo a http://createguid.com/


Como anotación al margen, que GUID es bastante largo; lo que significa una gran cantidad de bytes en su base de datos, si tiene millones de usuarios ... Por lo tanto, probablemente no se debe utilizar como cualquier tipo de clave primaria/externa.

¿Qué pasa con el uso del número entero más pequeño posible (que se ajusta a la cantidad de usuarios que tendrá) como clave principal/extranjera, ya que esa se duplicará en muchos lugares de la aplicación; y solo tiene el "ID de usuario largo" almacenado solo una vez, en su tabla de usuario?

+0

Existen contraseñas para los usuarios, sí ... Creo que he profundizado un poco ... Básicamente solo necesito una forma segura de mantener al usuario algo seguro, pero también solo para identificar al usuario en la lógica de db. Estoy de acuerdo con que las personas vean la identificación pública del usuario, ya que su ID de nivel de DB está oculta y es única. Tampoco tendrán acceso al servicio web y necesitarán ser autenticados para acceder a cualquier función que sea peligrosa. – brack

+0

Además, la intención de este ID debe almacenarse como usted mencionó: deseo almacenar solo el ID de usuario largo en la tabla principal del usuario y hacer referencia a él a través de otras tablas de usuario. Estoy usando un ID int incremental, pero quiero mantenerlo oculto y nunca exponerlo fuera de PHP y MySQL. Gracias – brack

0

¿Ha considerado utilizar un UUID?

Una rápida google search produce algunos buenos recursos/enlaces.

0

Personalmente uso md5 (uniqid (mt_rand(), true)) que creará un identificador de 32 caracteres (un número hexadecimal de 128 bits) que es extremadamente difícil de predecir.

1

Escribí esta clase que le da una identificación única de 24 caracteres, compatible con el campo de identificación de MongoDB (y usando la misma lógica para construirlo). Puede ser útil en el futuro

<?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