2010-03-18 12 views
9

uniqid() función devuelve un número hexadecimal largo de 13 dígitos. De acuerdo con el spec in php.net site, la función usa microtime para generar el valor único.¿Por qué la función uniqid de PHP devuelve solo 13 dígitos y no 14?

Pero microtime números devuelve en formato de cadena como la siguiente:

"0.70352700 12689396875" 

que son básicamente los microsegundos y los segundos transcurridos desde 1970. Este es un número decimal 9 + 11 dígitos.

La conversión de un número decimal de 20 en hexadecimal daría lugar a un 16 dígitos hexadecimal NO a 13 dígitos uno.

También pensé en sacar el "0". parte que parece que nunca cambia, y los dos últimos dígitos de la parte microsec que parecen permanecer siempre "00". Hacer esto el número decimal sería sólo 9 + 11-3 dígitos de largo, pero todavía un número decimal de 17 dígitos cuando se convierten en hex resultaría en 14 dígitos número hexadecimal NO 13.

I no estoy interesado en OBTENER UNA IDENTIFICACIÓN ÚNICA DE OTRO MODO O UNA IDENTIFICACIÓN ÚNICA MÁS LARGA/CORTA SOLO ESTOY PREGUNTANDO SI ALGUIEN SABE POR QUÉ UNiqid DEVOLUYE SOLO 13 DÍGITOS.

Parece Nosense: si uniqid vuelve un dígito menos de microtime, significa que microtime reparte resultados que son más única de las que devuelve uniqid.

+0

Debe usar la opción more_entropy, le ofrece un resultado mucho más único. –

+1

No necesito más único, necesito saber por qué el resultado es de solo 13 caracteres de largo. Gracias de todos modos por la sugerencia. –

+0

Los bits más significativos de microtime no son muy frecuentes. Entonces son bastante inútiles cuando tratas de generar dos cadenas únicas en unos pocos milisegundos entre sí. Todas las marcas de tiempo para la próxima semana comenzarán con 126. Y, si logras llamar a uniqid() dos veces en el mismo microsegundo (ya sea en dos subprocesos diferentes o dos servidores diferentes), verás que sus resultados no serán muy único en absoluto. –

Respuesta

19

encontrado esto en http://www.php.net/manual/en/function.uniqid.php#95001

tiene sentido para mí. Comentar si necesita una explicación

Para el registro, el función subyacente a uniqid() parece ser aproximadamente como sigue:

$ m = microtime (true); sprintf ("% 8x% 05x \ n", piso ($ m), ($ m-floor ($ m)) * 1000000);

En otras palabras, los primeros 8 caracteres hexadecimales = Unixtime, los últimos 5 caracteres hexadecimales = microsegundos. Es por eso que tiene una precisión de microsegundos. Además, proporciona un medio por el cual a ingeniería inversa del momento en que se generó un uniqid :

fecha ("r", hexdec (substr (uniqid(), 0,8)));

cada vez más a medida que avanza más abajo en la cadena , el número se convierte en "más único" con el tiempo, con la excepción de dígito 9, donde la prevalencia del número es 0..3> 4> 5..f, debido a la diferencia entre 10^6 y 16^5 (este es presumiblemente cierto para los dígitos restantes, pero mucho menos perceptible).

7

creo que el número generado por uniqid es basado en la hora actual en microsegundos - pero no es que el tiempo: el cálculo es probablemente un poco más difícil que usted piensa.

Aún así, si necesita más de 13 dígitos, puede pasar true como un segundo parámetro al uniqid, para tener más entropía, y le dará una cadena de 23 caracteres de longitud.


Por ejemplo, con esta porción de código:

var_dump(uniqid()); 
var_dump(uniqid('', true)); 

acabo de recibir:

string '4ba284384e4ca' (length=13) 
string '4ba284384e4df9.73439132' (length=23) 
+0

Esto no responde a mi pregunta, el punto sigue siendo por qué la función uniqid devuelve un valor que tiene solo 13 caracteres de largo. Como falta un dígito, no puede ser tan único como la función microtime(). De todos modos, gracias por la sugerencia. –

+2

Los segundos de una marca de tiempo Unix pueden 'ajustarse' dentro de 8 caracteres hexadecimales hasta principios de febrero de 2106 ((hex) 'FFFFFFFF' es (dec)' 4294967295'). Un microsegundo es una millonésima de segundo, por lo que el valor de microsegundo más grande es '999999' (más grande y será el próximo segundo completo) o' F423F' en hexadecimal. Entonces: 13 caracteres hexadecimales para representar el tiempo de Unix al microsegundo. – salathe

0

Para un 32 carácter único de identificación intente esto:

$unique = uniqid(rand(), true); 

Para acortarlo simplemente use substr():

$unique = substr(uniqid(rand(), true), 16, 16); // 16 characters long 
+4

¿No afectaría eso seriamente las posibilidades de duplicados? – Tom

+0

Las posibilidades aún serían extremadamente pequeñas y casi nunca sucederían. Sin embargo, si el objetivo era garantizar la máxima exclusividad, debería usarse todo el MD5. –

+2

Está agregando caracteres, pero reduciendo la entropía y la singularidad. –

-3

Según el manual de PHP, el valor predeterminado es 13 con $ more_entropy configurado en true será 23, pero siempre terminará con una marca de tiempo Unix.

A menudo uso $uid = md5(uniqid());

Actualización:
Ahora bien, esto le dará 32 caracteres con una mínima posibilidad de colisión es esta vida.

md5(uniqid(mt_rand(), true)); 
+4

' md5() 'no introduce más entropía en absoluto. En todo caso, se elimina un poco, ya que hay una pequeña posibilidad de colisión hash. –

+1

'md5' no es resistente a colisiones y no debe usarse como para este – Petah

+0

Lo siento, mal, olvidé por completo agregar el ejemplo completo md5 (uniqid (mt_rand(), true)); uniqid es el que tiene más entropía. –

Cuestiones relacionadas