2010-07-31 40 views
28

En php, ¿hay alguna manera de dar un hash único a partir de una cadena, pero que el hash está formado únicamente por números?php: ¿número solo hash?

ejemplo:

return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6 

pero necesito

return numhash(234); // returns 00978902923102372190 
(20 numbers only) 

el problema aquí es que quiero que el hash a ser corta.

editar: OK déjame explicarte la historia anterior aquí. Tengo un sitio que tiene una identificación para cada persona registrada, también necesito una identificación para que la persona la use y la cambie (por lo tanto, no puede ser demasiado larga), hasta ahora la numeración de ID ha sido 00001, 00002, 00003, etc. ...

  1. esto hace que algunas personas se vean más importante
  2. esto revela información sobre las aplicaciones que no quiero revelar.

Para corregir el punto 1 y 2 Necesito "ocultar" el número mientras lo mantengo único.

Respuesta

56

Un hash MD5 o SHA1 en PHP devuelve un número hexadecimal, por lo que todo lo que tiene que hacer es convertir las bases. PHP tiene una función que puede hacer esto para usted:

$bignum = hexdec(md5("test")); 

o

$bignum = hexdec(sha1("test")); 

PHP Manual for hexdec

Puesto que usted quiere un número de tamaño limitado, que luego podría utilizar división modular para ponerlo en una rango que quieres

$smallnum = $bignum % [put your upper bound here] 

EDITAR

Como señaló Artefacto en los comentarios, utilizando este enfoque se traducirá en un número más allá del tamaño máximo de un número entero en PHP, y el resultado después de la división modular siempre será 0 Sin embargo, tomar una subcadena del hash que contiene los primeros 16 caracteres no tiene este problema. versión revisada para calcular el número inicial grande:

$bignum = hexdec(substr(sha1("test"), 0, 15)); 
+0

¿Qué ocurre si limito la variable 'prueba' a un conjunto limitado de números? ¿habría alguna manera de reducir el tamaño de hash? –

+0

@YuriKolovsky - El tamaño de hash final se determinará por cualquier límite superior que utilizó para la división modular en el segundo paso. Por ejemplo, si desea que sus valores hash sean todos de 5 dígitos, puede usar '$ smallnum = $ bignum% 99999'. Esto funcionará independientemente de lo que se ponga en el hash inicial MD5 o SHA1. – derekerdmann

+0

@derekerdmann esto parece exactamente lo que necesito: D –

1

En primer lugar, md5 está básicamente comprometido, por lo que no debería usarlo para nada más que hashing no crítico. PHP5 tiene la función hash(), vea http://www.php.net/manual/en/function.hash.php.

Establecer el último parámetro en verdadero le dará una cadena de datos binarios. Alternativamente, podría dividir el hash hexadecimal resultante en pedazos de 2 caracteres y convertirlos en enteros individualmente, pero espero que sea mucho más lento.

+1

la velocidad no es un problema, el único problema que tengo es que el num hash es único no ridículamente largo. –

14

Puede probar crc32().Consulte la documentación en: http://php.net/manual/en/function.crc32.php

$checksum = crc32("The quick brown fox jumped over the lazy dog."); 
printf("%u\n", $checksum); // prints 2191738434 

Dicho esto, debe crcúnica usarse para validate the integrity of data.

3

Hay algunas buenas respuestas, pero para mí los enfoques parecen tontos.
Primero obligan a php a crear un número hexadecimal, luego lo convierten de nuevo (hexdec) en un BigInteger y luego lo reducen a una cantidad de letras ... ¡esto es mucho trabajo!

En vez por qué no

Leer el hash como binarios:

$binhash = md5('[input value]', true); 

a continuación, utilizando

$numhash = unpack('N2', $binhash); //- or 'V2' for little endian 

para lanzar este como dos INT s ($numhash es una matriz de dos elementos). Ahora puede reducir el número de bits en el número simplemente usando una operación AND. por ejemplo:

$result = $numhash[1] & 0x000FFFFF; //- to get numbers between 0 and 1048575 

pero ten cuidado de las colisiones! Reducir el número significa aumentar la probabilidad de dos [valores de entrada] diferentes con la misma salida.

Creo que la forma mucho mejor sería el uso de "ID-Crypting" con una función Bijectiv. ¡Así que no podría haber colisiones! Para el más simple tipo sólo tiene que utilizar un Ejemplo Affine_cipher

con max rango de valores de entrada de 0 a 25:

function numcrypt($a) 
{ 
    return ($a * 15) % 26; 
} 

function unnumcrypt($a) 
{ 
    return ($a * 7) % 26; 
} 

de salida:

numcrypt(1) : 15 
numcrypt(2) : 4 
numcrypt(3) : 19 

unnumcrypt(15) : 1 
unnumcrypt(4) : 2 
unnumcrypt(19) : 3 

por ejemplo

$id = unnumcrypt($_GET('userid')); 

... do something with the ID ... 

echo '<a href="do.php?userid='. numcrypt($id) . '"> go </a>'; 

por supuesto esto no es seguro, pero si no se conoce el método utilizado para su cifrado entonces no hay razones de seguridad a continuación de esta manera es más rápido y seguro de colisión.

+0

No entiendo cómo usar tu segunda solución para obtener un hash numérico, ¿podrías elaborar algo más? –

+0

no es un hash, pero puede usar, por ejemplo, Blowfish para cubrir sus identificaciones a un número "aleatorio" único. El usuario no puede calcular "ID + 1". Al final puede usar esto como un método proxy: su aplicación interna usa "ID: 1,2,3, ..." pero usted le proporciona los números encriptados a su usuario. Muchos lados grandes lo hacen de esta manera: p. las google-cookies son identificadores encriptados – Thomas

+0

¿Cómo se puede revertir (o empacar()) la matriz 'unpack ('N2', ...)'? – Xeoncross

5

El problema de cortar la patata son las colisiones, para evitar que Proveedores:

return hexdec(crc32("Hello World")); 

El crc32():

genera los cíclico polinomio redundancia suma de comprobación de 32 bits longitudes de la str. Esto se usa generalmente para validar la integridad de los datos que se transmiten.

Eso nos da un número entero de 32 bits, negativo en la instalación de 32 bits, o positivo en los 64 bits. Este entero podría almacenarse como una ID en una base de datos. Esto no tiene problemas de colisión, porque encaja en la variable de 32 bits, una vez que la convierte a decimal con la función hexdec().

0

Probar hashid.
Tiene un número de hash en el formato que puede definir. Los formatos incluyen cuántos personajes y qué personaje incluye.
Ejemplo:
$ hashids-> encode (1);
Devolverá "28630" depende de su formato,

Cuestiones relacionadas