¿Existe alguna forma de cifrado que pueda tomar una cadena de cualquier longitud y producir un hash de menos de 10 caracteres? Quiero producir identificaciones razonablemente únicas pero basadas en el contenido del mensaje, en lugar de al azar.
Sin embargo, puedo vivir con la restricción de los mensajes a valores enteros, si las cadenas de longitud arbitraria son imposibles. Sin embargo, el hash no debe ser similar para dos enteros consecutivos, en ese caso.
encryption
uniqueidentifier
rath3r
fuente
fuente
Respuestas:
Puede utilizar cualquier algoritmo hash comúnmente disponible (por ejemplo, SHA-1), que le dará un resultado un poco más largo de lo que necesita. Simplemente trunca el resultado a la longitud deseada, que puede ser lo suficientemente buena.
Por ejemplo, en Python:
fuente
hash(a)
choca conhash(b)
,base64(hash(a))
también choca conbase64(hash(b))
.sha1
colisiona , pero esta es otra historia). Si tiene un hash de 10 caracteres, obtendrá una entropía más alta si está codificado conbase64
vsbase16
(o hexadecimal). ¿Qué tan alto? Conbase16
obtienes 4 bits de información por carácter, conbase64
esta cifra es de 6 bits / char. En total, un hash "hexadecimal" de 10 caracteres tendrá 40 bits de entropía, mientras que una base64 de 60 bits. Entonces es un poco más resistente, perdón si no fui super claro.Si no necesita un algoritmo que sea fuerte contra la modificación intencional, encontré un algoritmo llamado adler32 que produce resultados bastante cortos (~ 8 caracteres). Elíjalo del menú desplegable aquí para probarlo:
http://www.sha1-online.com/
fuente
Necesita hash del contenido para obtener un resumen. Hay muchos hash disponibles, pero 10 caracteres es bastante pequeño para el conjunto de resultados. Hace mucho tiempo, la gente usaba CRC-32, que produce un hash de 33 bits (básicamente 4 caracteres más un bit). También existe CRC-64 que produce un hash de 65 bits. MD5, que produce un hash de 128 bits (16 bytes / caracteres) se considera roto para fines criptográficos porque se pueden encontrar dos mensajes que tienen el mismo hash. No hace falta decir que cada vez que cree un resumen de 16 bytes a partir de un mensaje de longitud arbitraria, terminará con duplicados. Cuanto más corto sea el resumen, mayor será el riesgo de colisiones.
Sin embargo, su preocupación de que el hash no sea similar para dos mensajes consecutivos (ya sean enteros o no) debería ser cierta con todos los hash. Incluso un cambio de un solo bit en el mensaje original debería producir un resumen resultante muy diferente.
Entonces, usar algo como CRC-64 (y base-64'ing el resultado) debería llevarlo al vecindario que está buscando.
fuente
Solo resumiendo una respuesta que fue útil para mí (señalando el comentario de @ erasmospunk sobre el uso de la codificación base-64). Mi objetivo era tener una cadena corta que en su mayoría fuera única ...
No soy un experto, así que corrija esto si tiene algún error evidente (en Python nuevamente como la respuesta aceptada):
El
result
aquí está usando más que solo caracteres hexadecimales (lo que obtendría si los usarahash.hexdigest()
) por lo que es menos probable que haya una colisión (es decir, debería ser más seguro truncar que un resumen hexadecimal).Nota: Usando UUID4 (aleatorio). Consulte http://en.wikipedia.org/wiki/Universally_unique_identifier para los otros tipos.
fuente
Puede usar un algoritmo hash existente que produzca algo corto, como MD5 (128 bits) o SHA1 (160). Luego, puede acortarlo aún más mediante XORing de secciones del resumen con otras secciones. Esto aumentará la posibilidad de colisiones, pero no tan mal como simplemente truncar el resumen.
Además, puede incluir la longitud de los datos originales como parte del resultado para hacerlo más exclusivo. Por ejemplo, XORing de la primera mitad de un resumen MD5 con la segunda mitad daría como resultado 64 bits. Agregue 32 bits para la longitud de los datos (o menos si sabe que la longitud siempre cabrá en menos bits). Eso daría como resultado un resultado de 96 bits (12 bytes) que luego podría convertir en una cadena hexadecimal de 24 caracteres. Alternativamente, puede usar la codificación base 64 para hacerlo aún más corto.
fuente
Si lo necesita
"sub-10-character hash"
, puede usar el algoritmo Fletcher-32 que produce hash de 8 caracteres (32 bits), CRC-32 o Adler-32 .CRC-32 es más lento que Adler32 en un factor de 20% a 100%.
Fletcher-32 es un poco más confiable que Adler-32. Tiene un costo computacional más bajo que la suma de comprobación de Adler: comparación de Fletcher vs Adler .
A continuación, se muestra un programa de muestra con algunas implementaciones de Fletcher:
Salida:
Está de acuerdo con los vectores de prueba :
Adler-32 tiene una debilidad para los mensajes cortos con unos pocos cientos de bytes, porque las sumas de comprobación para estos mensajes tienen una cobertura pobre de los 32 bits disponibles. Mira esto:
El algoritmo Adler32 no es lo suficientemente complejo como para competir con sumas de comprobación comparables .
fuente
Simplemente ejecute esto en una terminal (en MacOS o Linux):
8 caracteres de largo.
fuente
Puede usar la biblioteca hashlib para Python. Los algoritmos shake_128 y shake_256 proporcionan valores hash de longitud variable. Aquí hay un código de trabajo (Python3):
Observe que con un parámetro de longitud x (5 en el ejemplo) la función devuelve un valor hash de longitud 2x .
fuente
Ahora es 2019 y hay mejores opciones. A saber, xxhash .
fuente
Necesitaba algo parecido a una función de reducción de cadena simple recientemente. Básicamente, el código se parecía a esto (código C / C ++ más adelante):
Probablemente tenga más colisiones de las que se podrían desear, pero no está diseñado para usarse como función hash criptográfica. Puede probar varios multiplicadores (es decir, cambiar el 37 a otro número primo) si obtiene demasiadas colisiones. Una de las características interesantes de este fragmento es que cuando Src es más corto que Dest, Dest termina con la cadena de entrada tal cual (0 * 37 + valor = valor). Si desea algo "legible" al final del proceso, Normalize ajustará los bytes transformados a costa de aumentar las colisiones.
Fuente:
https://github.com/cubiclesoft/cross-platform-cpp/blob/master/sync/sync_util.cpp
fuente
DestSize
mayor de 4 (32 bits) cuando el hash en sí es tan cutre? Si quisiera la resistencia a colisiones proporcionada por una salida mayor que un int, usaría SHA.