¿Qué es una buena función Hash? Vi muchas funciones de hash y aplicaciones en mis cursos de estructuras de datos en la universidad, pero principalmente entendí que es bastante difícil hacer una buena función de hash. Como regla general para evitar colisiones, mi profesor dijo que:
function Hash(key)
return key mod PrimeNumber
end
(mod es el operador% en C y lenguajes similares)
con el número primo como el tamaño de la tabla hash. Entiendo que es una función algo buena para evitar colisiones y una rápida, pero ¿cómo puedo hacer una mejor? ¿Hay mejores funciones hash para las teclas de cadena frente a las teclas numéricas?
algorithm
language-agnostic
hash
Hoffmann
fuente
fuente
Respuestas:
Para hacer búsquedas de tablas hash "normales" en básicamente cualquier tipo de datos, esta de Paul Hsieh es la mejor que he usado.
http://www.azillionmonkeys.com/qed/hash.html
Si te importa la seguridad criptográfica o cualquier otra cosa más avanzada, entonces YMMV. Si solo desea una función hash de propósito general para una búsqueda de tabla hash, entonces esto es lo que está buscando.
fuente
No existe una "buena función hash" para los hash universales (ed. Sí, sé que existe el "hash universal", pero eso no es lo que quise decir). Dependiendo del contexto, diferentes criterios determinan la calidad de un hash. Dos personas ya mencionaron SHA. Este es un hash criptográfico y no es del todo bueno para las tablas hash, lo que probablemente quieras decir.
Las tablas hash tienen requisitos muy diferentes. Pero aún así, encontrar una buena función hash universalmente es difícil porque los diferentes tipos de datos exponen información diferente que puede ser hash. Como regla general, es bueno considerar toda la información que un tipo contiene por igual. Esto no siempre es fácil o incluso posible. Por razones de estadísticas (y por lo tanto colisión), también es importante generar una buena distribución en el espacio del problema, es decir, todos los objetos posibles. Esto significa que cuando los números hash entre 100 y 1050 no es bueno dejar que el dígito más significativo juegue un papel importante en el hash porque para ~ 90% de los objetos, este dígito será 0. Es mucho más importante dejar que los últimos tres los dígitos determinan el hash.
Del mismo modo, cuando se combinan cadenas, es importante tener en cuenta todos los caracteres, excepto cuando se sabe de antemano que los primeros tres caracteres de todas las cadenas serán los mismos; considerando esto, entonces es un desperdicio.
Este es en realidad uno de los casos en los que aconsejo leer lo que Knuth tiene que decir en The Art of Computer Programming , vol. 3. Otra buena lectura es The Art of Hashing de Julienne Walker .
fuente
Hay dos propósitos principales de las funciones de hash:
Es imposible recomendar un hash sin saber para qué lo está utilizando.
Si solo está haciendo una tabla hash en un programa, entonces no necesita preocuparse por cuán reversible o pirateable es el algoritmo ... SHA-1 o AES es completamente innecesario para esto, sería mejor usar Una variación de FNV . FNV logra una mejor dispersión (y, por lo tanto, menos colisiones) que un simple mod principal como usted mencionó, y es más adaptable a diferentes tamaños de entrada.
Si está utilizando los hash para ocultar y autenticar información pública (como el hash de una contraseña o un documento), entonces debe usar uno de los principales algoritmos de hash examinados por el escrutinio público. El Hash Function Lounge es un buen lugar para comenzar.
fuente
Este es un ejemplo de uno bueno y también un ejemplo de por qué nunca querrías escribir uno. Es un Hash Fowler / Noll / Vo (FNV) que es a partes iguales genio de la informática y vudú puro:
Editar:
fuente
Yo diría que la regla general es no tirar la tuya. Intente usar algo que haya sido probado exhaustivamente, por ejemplo, SHA-1 o algo similar.
fuente
Una buena función hash tiene las siguientes propiedades:
Dado un hash de un mensaje, es computacionalmente inviable que un atacante encuentre otro mensaje de modo que sus hashes sean idénticos.
Dado un par de mensajes, m 'ym, es computacionalmente inviable encontrar dos tales que h (m) = h (m')
Los dos casos no son lo mismo. En el primer caso, hay un hash preexistente para el que estás tratando de encontrar una colisión. En el segundo caso, se está tratando de encontrar alguna dos mensajes que entran en colisión. La segunda tarea es significativamente más fácil debido a la "paradoja" de cumpleaños.
Cuando el rendimiento no es un gran problema, siempre debe usar una función hash segura. Hay ataques muy inteligentes que se pueden realizar forzando colisiones en un hash. Si usa algo fuerte desde el principio, se protegerá contra estos.
No use MD5 o SHA-1 en nuevos diseños. La mayoría de los criptógrafos, incluido yo, los considerarían rotos. La principal fuente de debilidad en ambos diseños es que la segunda propiedad, que describí anteriormente, no es válida para estas construcciones. Si un atacante puede generar dos mensajes, m y m ', ambos hash al mismo valor pueden usar estos mensajes en su contra. SHA-1 y MD5 también sufren ataques de extensión de mensajes, que pueden debilitar fatalmente su aplicación si no tiene cuidado.
Un hash más moderno como Whirpool es una mejor opción. No sufre estos ataques de extensión de mensajes y utiliza las mismas matemáticas que AES para probar la seguridad contra una variedad de ataques.
¡Espero que ayude!
fuente
Lo que estás diciendo aquí es que quieres tener uno que tenga resistencia a la colisión. Intenta usar SHA-2. O intente utilizar un cifrado de bloque (bueno) en una función de compresión unidireccional (nunca lo había intentado antes), como AES en el modo Miyaguchi-Preenel. El problema con eso es que necesita:
1) tener una vía intravenosa. Intenta usar los primeros 256 bits de las partes fraccionarias de la constante de Khinchin o algo así. 2) tener un esquema de relleno. Fácil. Llévelo de un hash como MD5 o SHA-3 (Keccak [pronunciado 'ket-chak']). Si no te importa la seguridad (algunos otros dijeron esto), mira FNV o look2 de Bob Jenkins (en realidad soy el primero que recomienda look2) También prueba MurmurHash, es rápido (mira esto: .16 cpb )
fuente