Saltar al contenido

¿Se puede utilizar CRC32 como función hash?

Después de investigar con expertos en esta materia, programadores de deferentes áreas y profesores hemos dado con la solución a la cuestión y la compartimos en esta publicación.

Solución:

CRC32 funciona muy bien como un algoritmo hash. El todo el punto de un CRC es hacer un hash de un flujo de bytes con la menor cantidad de colisiones posible. Dicho esto, hay algunos puntos a considerar:

  • Los CRC no son seguros. Para un hash seguro, necesita un algoritmo mucho más costoso desde el punto de vista informático. Para un simple hash de cubo, la seguridad generalmente no es un problema.

  • Existen diferentes sabores de CRC con diferentes propiedades. Asegúrese de utilizar el algoritmo correcto, por ejemplo, con el polinomio hash 0x11EDC6F41 (CRC32C), que es la opción óptima de uso general.

  • Como compensación entre velocidad y calidad de hash, la instrucción x86 CRC32 es difícil de superar. Sin embargo, esta instrucción no existe en las CPU más antiguas, así que tenga cuidado con los problemas de portabilidad.

—- EDITAR —-

Mark Adler proporcionó un enlace a un artículo útil para la evaluación de hash de Bret Mulvey. Utilizando el código fuente proporcionado en el artículo, ejecuté la “prueba de cubo” tanto para CRC32C como para Jenkins96. Estas tablas muestran la probabilidad de que una distribución verdaderamente uniforme sea peor que el resultado medido por casualidad. Entonces, números más altos son mejores. El autor consideró que 0.05 o menos es débil y 0.01 o menos es muy débil. Confío completamente en el autor en todo esto y solo estoy informando los resultados.

Coloqué un * en todas las instancias donde CRC32C funcionó mejor que Jenkins96. Según este simple recuento, CRC32C fue un hash más uniforme que Jenkins96 54 de 96 veces. Especialmente Si puede utilizar la instrucción x86 CRC32, la compensación de velocidad y rendimiento es excelente.

CRC32C (0x1EDC6F41)

       Uniform keys        Text keys         Sparse keys

Bits  Lower    Upper     Lower    Upper     Lower    Upper
 1    0.671   *0.671    *1.000    0.120    *0.572   *0.572
 2   *0.706   *0.165    *0.729   *0.919     0.277    0.440
 3   *0.878   *0.879    *0.556    0.362    *0.535   *0.542
 4    0.573    0.332     0.433    0.462    *0.855    0.393
 5    0.023   *0.681     0.470    0.907     0.266    0.059
 6   *0.145   *0.523     0.354   *0.172    *0.336    0.588
 7    0.424    0.722     0.172   *0.736     0.184   *0.842
 8   *0.767    0.507    *0.533    0.437     0.337    0.321
 9    0.480    0.725    *0.753   *0.807    *0.618    0.025
10   *0.719    0.161    *0.970   *0.740    *0.789    0.344
11   *0.610    0.225    *0.849   *0.814    *0.854   *0.003
12   *0.979   *0.239    *0.709    0.786     0.171   *0.865
13   *0.515    0.395     0.192    0.600     0.869   *0.238
14    0.089   *0.609     0.055   *0.414    *0.286   *0.398
15   *0.372   *0.719    *0.944    0.100    *0.852   *0.300
16    0.015   *0.946    *0.467    0.459     0.372   *0.793

Y para Jenkins96, que el autor del artículo consideró un excelente hash:

Jenkins96

      Uniform keys         Text keys         Sparse keys

Bits  Lower    Upper     Lower    Upper     Lower    Upper
 1    0.888    0.572     0.090    0.322     0.090    0.203
 2    0.198    0.027     0.505    0.447     0.729    0.825
 3    0.444    0.510     0.360    0.444     0.467    0.540
 4    0.974    0.783     0.724    0.971     0.439    0.902
 5    0.308    0.383     0.686    0.940     0.424    0.119
 6    0.138    0.505     0.907    0.103     0.300    0.891
 7    0.710    0.956     0.202    0.407     0.792    0.506
 8    0.031    0.552     0.229    0.573     0.407    0.688
 9    0.682    0.990     0.276    0.075     0.269    0.543
10    0.382    0.933     0.038    0.559     0.746    0.511
11    0.043    0.918     0.101    0.290     0.584    0.822
12    0.895    0.036     0.207    0.966     0.486    0.533
13    0.290    0.872     0.902    0.934     0.877    0.155
14    0.859    0.568     0.428    0.027     0.136    0.265
15    0.290    0.420     0.915    0.465     0.532    0.059
16    0.155    0.922     0.036    0.577     0.545    0.336

Obviamente podrías, pero no deberías. Un crc32 distribuye mal los bits de entrada al hash. Además, ciertamente no debería usarse nunca como un hash unidireccional, ya que no lo es. Es muy fácil modificar un mensaje para producir un crc determinado.

Utilice un algoritmo hash diseñado para el propósito que tiene en mente, sea lo que sea.

No sé por qué Mark Adler dijo que “crc32 distribuye mal los bits de entrada al hash”. No hay un solo bit en el hash crc32 que sea exactamente igual a los bits de entrada. Cualquier bit del hash es una combinación lineal de los bits de entrada. En segundo lugar, crc siempre asigna uniformemente el mismo número de diferentes secuencias de entrada a un valor hash dado. Por ejemplo, si tiene un mensaje de 1000 bits de longitud, después de crc32, siempre puede encontrar 2 ^ (1000-32) secuencias que produzcan un valor hash dado, ni más ni menos.

Si no necesita la función de seguridad, crc puede servir perfectamente como hash.

En realidad, creo que otras funciones hash no seguras pueden ser más simples que crc, si necesita tener un crc más largo, por ejemplo, crc-256.

Calificaciones y reseñas

Eres capaz de sostener nuestra función ejecutando un comentario y dejando una valoración te estamos eternamente agradecidos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : / /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *