2010-02-10 36 views
25

Se dice que las tablas hash son la forma más rápida/mejor de almacenar/recuperar datos.¿Cómo escribir una función hash en C?

Mi comprensión de una tabla hash, hash es el siguiente (Por favor, corríjanme si estoy equivocado o por favor agregue Si hay algo más):

  • Una tabla Hash no es más que una matriz (simple o multidimensional) para almacenar valores.
  • Hashing es el proceso para encontrar el índice/ubicación en la matriz para insertar/recuperar los datos. Usted toma un elemento (s) de datos y lo pasa como una clave (s) a una función hash y obtendrá el índice/ubicación donde insertar/recuperar los datos.

Tengo una pregunta:

es la función hash utilizado para almacenar/recuperar los datos distintas de una función hash criptográfica utilizado en aplicaciones de seguridad para la autenticación como MD5, HMAC, SHA-1, etc. ..?

¿En qué forma (s) son diferentes?

  • Cómo escribir una función hash en C?
  • ¿Hay algún estándar o pautas para ello?
  • ¿Cómo nos aseguramos de que la salida de una función hash, es decir, el índice no está fuera de rango?

Sería grandioso si pudiera mencionar algunos buenos enlaces para entenderlos mejor.

+1

El rango se puede limitar con el operador del módulo (%). – tur1ng

+23

La siguiente página tiene varias implementaciones de funciones hash de propósito general implementadas en C (y en muchos otros idiomas): http://partow.net/programming/hashfunctions/index.html –

Respuesta

4

Bob Jenkins escribió una descripción en profundidad de su buena, aunque ligeramente obsoleta, hash function. El artículo tiene enlaces a funciones hash más nuevas y mejores, pero la descripción aborda las preocupaciones de construir una buena.

Además, la mayoría de las implementaciones de tablas hash realmente usan una matriz de listas vinculadas para resolver colisiones. Si solo quieres usar una matriz, entonces la función hash necesita verificar las colisiones y crear un nuevo índice hash.

Las funciones hash criptográficas que menciona podrían utilizarse como funciones hash para una tabla hash, pero son mucho más lentas que las funciones hash diseñadas para una tabla hash. La velocidad hace que los ataques de fuerza bruta sean más fáciles.

11

Un hash criptográfico hace hincapié en que sea difícil para cualquier persona crear una colisión intencionalmente. Para una tabla hash, normalmente se hace hincapié en producir un margen razonable de resultados rápidamente. Como tal, los dos suelen ser bastante diferentes (en particular, un hash criptográfico es normalmente un lote más lento).

Para una función hash típica, el resultado está limitado solo por el tipo, p. Ej. si devuelve un size_t, está perfectamente bien para devolver cualquier posible tamaño_t. Depende de usted reducir ese rango de salida al tamaño de su tabla (por ejemplo, utilizando el resto de la división por el tamaño de su tabla, que a menudo debería ser un número primo).

A modo de ejemplo, una función bastante típico de hash normal, podría ser algo como:

// warning: untested code. 
size_t hash(char const *input) { 

    const int ret_size = 32; 
    size_t ret = 0x555555; 
    const int per_char = 7; 

    while (*input) { 
     ret ^= *input++; 
     ret = ((ret << per_char) | (ret >> (ret_size - per_char)); 
    } 
    return ret; 
} 

La idea básica aquí es tener cada parte de la cadena de entrada afectar el resultado, y (lo más rápido posible) tienen cada parte del resultado afectado por al menos parte de la entrada. Tenga en cuenta que no lo recomiendo particularmente como una gran función hash, solo intento ilustrar algunos de los conceptos básicos de lo que está tratando de lograr.

+0

Las funciones hash criptográficas no son necesariamente lentas. En particular, se informó que la función hash MD4 es más rápida que CRC32 en algunas plataformas (basada en ARM, creo). Sin embargo, las funciones hash criptográficas tienden a tener una gran sobrecarga fija, lo que significa que serán lentas para pequeños mensajes de entrada. Una función como MD4 logra su ancho de banda de procesamiento muy alto (más de 600 MB/s en mi CPU Intel de 2,4 GHz) cuando el tamaño de entrada supera 1 KB o menos. Aún así, para pequeñas entradas (menos de 54 bytes), mi PC todavía calcula 8 millones de MD4 por segundo (con un solo núcleo). –

+0

@Thomas: Primero, aunque CRC32 puede ser razonablemente rápido, la mayoría de las funciones hash son bastante más rápidas. En segundo lugar, aunque ciertamente se pretendía que fuera un hash criptográfico, MD4 realmente ya no califica. Se rompió ampliamente hace años, generar una colisión es casi la misma velocidad que generar el hash original. Ver: http://www.stachliu.com/md4coll.c para una implementación. –

+0

Sé que MD4 se rompió, pero para fines no criptográficos (de los que estamos hablando) MD4 es bastante bueno; si las colisiones deliberadas son un problema, entonces se descarta por definición cada función hash no criptográfica. Cuando no hay un problema de seguridad, al menos se puede prever MD4. Algunos sistemas peer-to-peer usan MD4 para identificar elementos de archivo. En cuanto a las funciones criptográficas rápidas pero sólidas, existe una competencia constante para seleccionar una nueva. Consulte http://en.wikipedia.org/wiki/NIST_hash_function_competition para obtener más información (soy coautor de uno de los candidatos). –

0

Los objetivos de diseño son diferentes.

Con cryptographic hash functions desea, por ejemplo, que la función hash y la función hash no se puedan utilizar para determinar los datos originales o cualquier otro dato que produzca el mismo hash.

Las funciones hash usadas con tablas hash & otras estructuras de datos no necesitan tales propiedades de seguridad. A menudo es suficiente si la función hash es rápida y distribuirá el conjunto de entrada de manera uniforme en el conjunto de hashes posibles (para evitar clustering innecesarios/colisiones).