¿Qué función hash criptográfica debo elegir?


137

El marco .NET se entrega con 6 algoritmos de hashing diferentes:

  • MD5: 16 bytes (Tiempo de hash 500MB: 1462 ms)
  • SHA-1: 20 bytes (1644 ms)
  • SHA256: 32 bytes (5618 ms)
  • SHA384: 48 bytes (3839 ms)
  • SHA512: 64 bytes (3820 ms)
  • RIPEMD: 20 bytes (7066 ms)

Cada una de estas funciones se realiza de manera diferente; MD5 es el más rápido y RIPEMD es el más lento.

MD5 tiene la ventaja de que cabe en el tipo Guid incorporado; y es la base del UUID tipo 3 . El hash SHA-1 es la base del UUID tipo 5. Lo que los hace realmente fáciles de usar para la identificación.

MD5, sin embargo, es vulnerable a los ataques de colisión , SHA-1 también es vulnerable, pero en menor grado.

¿En qué condiciones debo usar qué algoritmo de hash?

Las preguntas particulares que realmente tengo curiosidad por ver respondidas son:

  • ¿No se puede confiar en MD5? En situaciones normales, cuando utiliza el algoritmo MD5 sin intención maliciosa y ningún tercero tiene ninguna intención maliciosa, esperaría CUALQUIER colisión (es decir, dos bytes arbitrarios [] que producen el mismo hash)

  • ¿Cuánto mejor es RIPEMD que SHA1? (si es mejor) es 5 veces más lento de calcular, pero el tamaño de hash es el mismo que SHA1.

  • ¿Cuáles son las probabilidades de obtener colisiones no maliciosas al codificar nombres de archivos (u otras cadenas cortas)? (Por ejemplo, 2 nombres de archivo aleatorios con el mismo hash MD5) (con MD5 / SHA1 / SHA2xx) En general, ¿cuáles son las probabilidades de colisiones no maliciosas?

Este es el punto de referencia que utilicé:

    static void TimeAction(string description, int iterations, Action func) {
        var watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < iterations; i++) {
            func();
        }
        watch.Stop();
        Console.Write(description);
        Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
    }

    static byte[] GetRandomBytes(int count) {
        var bytes = new byte[count];
        (new Random()).NextBytes(bytes);
        return bytes;
    }


    static void Main(string[] args) {

        var md5 = new MD5CryptoServiceProvider();
        var sha1 = new SHA1CryptoServiceProvider();
        var sha256 = new SHA256CryptoServiceProvider();
        var sha384 = new SHA384CryptoServiceProvider();
        var sha512 = new SHA512CryptoServiceProvider();
        var ripemd160 = new RIPEMD160Managed();

        var source = GetRandomBytes(1000 * 1024);

        var algorithms = new Dictionary<string,HashAlgorithm>();
        algorithms["md5"] = md5;
        algorithms["sha1"] = sha1;
        algorithms["sha256"] = sha256;
        algorithms["sha384"] = sha384;
        algorithms["sha512"] = sha512;
        algorithms["ripemd160"] = ripemd160;

        foreach (var pair in algorithms) {
            Console.WriteLine("Hash Length for {0} is {1}", 
                pair.Key, 
                pair.Value.ComputeHash(source).Length);
        }

        foreach (var pair in algorithms) {
            TimeAction(pair.Key + " calculation", 500, () =>
            {
                pair.Value.ComputeHash(source);
            });
        }

        Console.ReadKey();
    }

15
El hecho de que mencione que md5 encaja en el formato GUID (16 bytes) sugiere un malentendido fundamental. No se garantiza que un hash sea único, pero es raro (y difícil de falsificar si se usa en un sentido criptográfico) y se deriva de lo que es un hash, mientras que un GUID es, bueno, único pero no relacionado con el contenido del Lo que identifica. Se utilizan para fines muy diferentes.
Barry Wark

1
Corregir su no relacionado, es solo un hecho específico de implementación práctica. Entiendo que no puede caber infinito en 16 bytes. Puede obtener colisiones con CUALQUIER algoritmo de hash
Sam Saffron

55
Además, un Guid es único en la práctica, en teoría, si seguía generando Guid, eventualmente obtendría duplicados.
Sam Saffron

3
Realmente no deberías meter un hash en un GUID, incluso si encaja. El ejemplo más simple: dos copias del mismo archivo deben tener GUID diferentes, pero el mismo hash. Las primeras 8 letras del nombre de una persona también encajan bastante bien en 16 bytes.
dbkk

2
@ user2332868 La ruptura de SHA-1 no tiene ningún efecto sobre la probabilidad de colisiones accidentales . Cuando una intención maliciosa es una amenaza para su uso, creo que elegir a ciegas cualquier función hash es incorrecto, y debe dedicar tiempo a realizar análisis de riesgo / costo para su caso específico.
Andrey Tarantsov

Respuestas:


138

En criptografía, las funciones hash proporcionan tres funciones separadas.

  1. Resistencia a la colisión : cuán difícil es para alguien encontrar dos mensajes ( cualquiera de los dos mensajes) que tengan el mismo hash.
  2. Resistencia previa a la imagen : dado un hash, ¿qué tan difícil es encontrar otro mensaje que tenga el mismo hash? También se conoce como función hash unidireccional .
  3. Segunda resistencia previa a la imagen : dado un mensaje, busque otro mensaje que tenga el mismo hash.

Estas propiedades están relacionadas pero son independientes. Por ejemplo, la resistencia a la colisión implica una segunda resistencia previa a la imagen, pero no al revés. Para cualquier aplicación dada, tendrá diferentes requisitos, necesitando una o más de estas propiedades. Una función hash para proteger las contraseñas en un servidor generalmente solo requerirá resistencia previa a la imagen, mientras que los resúmenes de mensajes requieren los tres.

Se ha demostrado que MD5 no es resistente a colisiones, sin embargo, eso no impide su uso en aplicaciones que no requieren resistencia a colisiones. De hecho, MD5 a menudo todavía se usa en aplicaciones donde el tamaño de clave y la velocidad más pequeños son beneficiosos. Dicho esto, debido a sus defectos, los investigadores recomiendan el uso de otras funciones hash en nuevos escenarios.

SHA1 tiene una falla que permite encontrar colisiones en teoría, mucho menos que los 2 ^ 80 pasos que requeriría una función hash segura de su longitud. El ataque se revisa continuamente y actualmente se puede realizar en ~ 2 ^ 63 pasos, apenas dentro del ámbito actual de computabilidad. Por esta razón, NIST está eliminando gradualmente el uso de SHA1, indicando que la familia SHA2 debe usarse después de 2010.

SHA2 es una nueva familia de funciones hash creadas después de SHA1. Actualmente no hay ataques conocidos contra las funciones SHA2. SHA256, 384 y 512 son parte de la familia SHA2, solo que usan diferentes longitudes de clave.

RIPEMD No puedo comentar demasiado, excepto para señalar que no es tan comúnmente utilizado como las familias SHA, por lo que no ha sido analizado tan de cerca por los investigadores criptográficos. Solo por esa razón, recomendaría el uso de funciones SHA sobre él. En la implementación que está utilizando, también parece bastante lenta, lo que lo hace menos útil.

En conclusión, no hay una mejor función: todo depende de para qué la necesite. Tenga en cuenta los defectos con cada uno y podrá elegir la función hash adecuada para su escenario.


1
Realmente aprecio que hayas entrado en este nivel de detalle. Esto es muy útil.
joelc

1
Para algunas aplicaciones, incluso una función hash sin grado criptográfico podría ser apropiada. El OP nunca mencionó si era específicamente para contraseñas, o para autenticación de desafío-respuesta, o para tokens de acceso, o simplemente para indexar un montón de cadenas / archivos. El rendimiento, por otro lado, es una preocupación para el OP ...
Seva Alekseyev

111

Todas las funciones hash están "rotas"

El principio del casillero dice que, por mucho que lo intentes, no puedes colocar más de 2 palomas en 2 agujeros (a menos que cortes las palomas). Del mismo modo, no puede caber 2 ^ 128 + 1 números en 2 ^ 128 espacios. Todas las funciones hash dan como resultado un hash de tamaño finito, esto significa que siempre puedes encontrar una colisión si buscas en secuencias de "tamaño finito" + 1. Simplemente no es factible hacerlo. No para MD5 y no para Skein .

MD5 / SHA1 / Sha2xx no tienen colisiones casuales

Todas las funciones hash tienen colisiones, es un hecho de la vida. Encontrar estas colisiones por accidente es el equivalente a ganar la lotería intergaláctica . Es decir, nadie gana la lotería intergaláctica , no es así como funciona la lotería. No se encontrará con un hash MD5 / SHA1 / SHA2XXX accidental, NUNCA. Cada palabra en cada diccionario, en cada idioma, tiene un valor diferente. Cada nombre de ruta, en cada máquina en todo el planeta tiene un hash MD5 / SHA1 / SHA2XXX diferente. ¿Cómo sé eso ?, puedes preguntar. Bueno, como dije antes, nadie gana la lotería intergaláctica, nunca.

Pero ... MD5 está roto

A veces el hecho de que está roto no importa .

Tal como está, no se conocen ataques previos a la imagen ni a la segunda imagen previa en MD5.

Entonces, ¿qué tiene de malo MD5? Es posible que un tercero genere 2 mensajes, uno de los cuales es MALO y el otro es BUENO, y ambos tienen el mismo valor. ( Ataque de colisión )

Sin embargo, la recomendación actual de RSA es no usar MD5 si necesita resistencia previa a la imagen. Las personas tienden a equivocarse con precaución cuando se trata de algoritmos de seguridad.

Entonces, ¿qué función hash debo usar en .NET?

  • Use MD5 si necesita la velocidad / tamaño y no le importan los ataques de cumpleaños o los ataques previos a la imagen.

Repita esto después de mí, no hay posibilidad de colisiones MD5 , las colisiones maliciosas se pueden diseñar cuidadosamente. Aunque hasta la fecha no se conocen ataques previos a la imagen en MD5, la línea de los expertos en seguridad es que MD5 no debe usarse donde necesita defenderse contra los ataques previos a la imagen. MISMO va para SHA1 .

Tenga en cuenta que no todos los algoritmos necesitan defenderse contra ataques de imagen previa o colisión. Tome el caso trivial de una búsqueda de primer paso para archivos duplicados en su HD.

  • Utilice la función basada en SHA2XX si desea una función hash criptográficamente segura.

Nadie ha encontrado alguna colisión SHA512. NUNCA. Lo han intentado realmente duro. Por lo demás, nadie encontró nunca ninguna colisión SHA256 o 384. .

  • No use SHA1 o RIPEMD a menos que sea para un escenario de interoperabilidad.

RIPMED no ha recibido la misma cantidad de escrutinio que SHAX y MD5. Tanto SHA1 como RIPEMD son vulnerables a los ataques de cumpleaños. Ambos son más lentos que MD5 en .NET y vienen en el incómodo tamaño de 20 bytes. No tiene sentido usar estas funciones, olvídate de ellas.

Los ataques de colisión SHA1 se redujeron a 2 ^ 52, no pasará mucho tiempo hasta que las colisiones SHA1 estén en libertad.

Para obtener información actualizada sobre las diversas funciones hash, eche un vistazo al zoológico de funciones hash .

Pero espera, hay más

Tener una función hash rápida puede ser una maldición. Por ejemplo: un uso muy común para las funciones hash es el almacenamiento de contraseñas. Esencialmente, calcula el hash de una contraseña combinada con una cadena aleatoria conocida (para impedir ataques de arco iris) y almacena ese hash en la base de datos.

El problema es que si un atacante obtiene un volcado de la base de datos, puede adivinar las contraseñas con bastante fuerza usando fuerza bruta. Cada combinación que intenta solo toma una fracción de milisegundo, y puede probar cientos de miles de contraseñas por segundo.

Para solucionar este problema, se puede usar el algoritmo bcrypt , está diseñado para ser lento, por lo que el atacante se ralentizará mucho si ataca un sistema que usa bcrypt. Recientemente, scrypt ha aparecido en los titulares y algunos lo consideran más efectivo que bcrypt, pero no conozco una implementación de .Net.


Si bien MD5 y SHA-1 se han debilitado, MD5 es mucho más débil que SHA-1, aunque solo un poco más rápido. Se han encontrado colisiones MD5 reales y se han utilizado para exploits del mundo real (falsificación de certificados de CA), pero que yo sepa no se han encontrado colisiones SHA-1 reales (aunque el número de operaciones se ha reducido considerablemente debido a la fuerza bruta). Y dado lo mucho más débil que es MD5, no me sorprendería si los segundos ataques de preimagen aparecieran antes para MD5 que para SHA-1. Por lo tanto, creo que debería usar SHA-1 si necesita velocidad y no resistencia a la colisión, y de lo contrario usar uno de la familia SHA-2.
Brian Campbell

1
@Brian es bastante claro que en los próximos años las personas podrán ejecutar ataques de colisión en SHA1, esto efectivamente hará que SHA1 sea tan útil como MD5. ejecutar el mismo ataque en los certificados SHA1 CA. El ataque depende de que una parte maliciosa cree un MAL y un BUEN certificado. No se conocen ataques de primage en MD5 y el hecho de que haya ataques de colisión no hace que los ataques previos a la imagen sean más o menos probables.
Sam Saffron

Se trata mucho menos de qué hash se usa para las contraseñas, que de lo que se usa para el hash. Si se conoce su sal, entonces su base de datos es inmediatamente vulnerable a un ataque de diccionario; si su sal es procesal y su sistema de archivos está comprometido, usted es (nuevamente) vulnerable; Si se omite su sal, se ve comprometido nuevamente. La seguridad en cuestión es, pase lo que pase, QUÉ es hash. Certificados, no los abordaré porque no los he tratado como programador (IE, creación, comprensión, etc.).
Robert K

El término roto tiene un significado específico en el contexto del hash, y no es el significado en el que esta respuesta pone énfasis. Todo lo que esta respuesta hará es causar confusión.
Joel McBeth

1
Esta es una excelente respuesta porque se centra en la practicidad. Los hashes se usan para otras cosas que no sean la seguridad (como generar claves de búsqueda de caché para datos no confidenciales o determinar si un objeto serializado ha cambiado). Las posibilidades de un ataque dirigido son prácticamente nulas (nunca digas nunca), e incluso si un ataque tuviera éxito, no tendría un impacto material. Excelente trabajo centrado en el impacto práctico (en lugar de teórico).
DVK

35

Actualizar:

Los tiempos han cambiado, tenemos un ganador SHA3. Recomendaría usar keccak (también conocido como SHA3 ) ganador del concurso SHA3.

Respuesta original

En orden de más débil a más fuerte, diría:

  1. RIPEMD ROTO, nunca debe usarse como se puede ver en este pdf
  2. MD-5 ROTO, nunca debe usarse, se puede romper en 2 minutos con una computadora portátil
  3. SHA-1 ROTO, nunca debe usarse, está roto en principio, los ataques mejoran cada semana
  4. SHA-2 DÉBIL, probablemente se romperá en los próximos años. Se han encontrado algunas debilidades. Tenga en cuenta que, por lo general, cuanto mayor sea el tamaño de la clave, más difícil será romper la función hash. Si bien el tamaño de la clave = fuerza no siempre es cierto, es mayormente cierto. Entonces SHA-256 es probablemente más débil que SHA-512.
  5. Skein SIN DEBILIDADES CONOCIDAS, es candidata para SHA-3 . Es bastante nuevo y, por lo tanto, no se ha probado. Se ha implementado en varios idiomas.
  6. MD6 SIN DEBILIDADES CONOCIDAS, es otro candidato para SHA-3. Probablemente más fuerte que Skien, pero más lento en máquinas de un solo núcleo. Al igual que Skien, no ha sido probado. Algunos desarrolladores con mentalidad de seguridad lo están utilizando, en roles de misión crítica .

Personalmente usaría MD6, porque uno nunca puede ser demasiado paranoico. Si la velocidad es una preocupación real, miraría Skein o SHA-256.


55
No pondría a Skein y MD6 tan alto en la lista; hay una razón por la cual la competencia SHA-3 no se terminará hasta finales de 2012. Lleva mucho tiempo y muchos ojos estar convencidos de que una función hash es realmente segura, y ninguna de estas funciones han existido el tiempo suficiente para eso todavía.
Eric Burnett

Estoy de acuerdo con sus sentimientos, pero creo que la comunidad está en una posición extraña. Todas las funciones hash en uso están peligrosamente cerca de romperse (tal vez, tal vez, no SHA2 256-512) y, sin embargo, tenemos que esperar a 2012 para elegir un reemplazo. elija su veneno: débil / roto o no probado (la mayoría de los candidatos del NIST no han sido públicos durante más de 6 meses)? Decisión difícil.
Ethan Heilman

55
RIPEMD está roto, pero RIPEMD-128/160/256 son diferentes y no están rotos.
Bwooce

No conozco ninguna implementación de Skein para .NET. Me he encontrado con SkeinFish y nskein, y ambos fueron muy lentos.
Cocowalla

1
Esperaría con el uso de SHA-3 hasta que el estándar real esté disponible, al menos si realmente desea seguir un estándar. El algoritmo en sí tiene demasiadas opciones.
Paŭlo Ebermann

3

En defensa de MD5, no hay forma conocida de producir un archivo con un hash MD5 arbitrario. El autor original debe planificar con anticipación para tener una colisión funcional. Por lo tanto, si el receptor confía en el remitente, MD5 está bien. MD5 se rompe si el firmante es malicioso, pero no se sabe que sea vulnerable a los ataques de hombre en el medio.


1
Si bien no soy un experto en este campo, ¿no es posible calcular hoy en día los hash MD5 arbitrarios por fuerza bruta?
mafu

@mafu: respuesta tardía aquí, pero es posible calcular cualquier hash a través de la fuerza bruta. Puede que tarde mucho tiempo.
Warty

@ItzWarty Me refería específicamente al tiempo necesario: dado que MD5 es bastante corto, pensé que podría ser posible simplemente arrojarle una fuente de computación razonable (E3, o una grilla de computadora barata, algunas máquinas con algunas tarjetas gráficas, algo en ese sentido) y poder calcular un hash MD5 arbitrario dentro de, por ejemplo, unos días.
mafu

@mafu Un ataque previo a la imagen cuesta 2 ^ 127 invocaciones de hash para un hash de 128 bits. Esto está lejos de ser factible. Las invocaciones 2 ^ 80 son factibles pero ya son muy caras.
CodesInChaos

2

El que usa realmente depende de para qué lo está usando. Si solo quieres asegurarte de que los archivos no se corrompan en tránsito y no te preocupes tanto por la seguridad, hazlo rápido y pequeño. Si necesita firmas digitales para acuerdos de rescate federal de miles de millones de dólares y necesita asegurarse de que no se falsifiquen, haga las cosas difíciles de falsificar y frenar.


1
Muchas veces, cuando discuto soluciones al problema, menciono que uso MD5 para una identidad rápida (trocear una cadena), dicen "pero md5 está roto ... no lo use, use sha1" ... Realmente no me suscribo a esto. si algo se rompe tan fundamentalmente con algunos de los más débiles hashs que se deben evitar ... por ejemplo, casos verdaderas obras donde los datos normal produce colisiones
Sam azafrán

Dado que MD5 funcionó bien para millones de personas durante quince años, sospecho que está bien si la seguridad de hash no es crucial.
mqp

2
@sambo MD5 funciona bien para casi cualquier caso, excepto cuando la seguridad / integridad real de su sistema depende de la prevención de colisiones.
Rex M

2

Me gustaría comentar (antes de que md5 se rompa) que todavía uso md5 ampliamente a pesar de su abrumadora fragmentación para muchas criptomonedas.

Siempre y cuando no te importe protegerte contra colisiones (también puedes usar md5 de forma segura en un hmac) y quieres la velocidad (a veces quieres un hash más lento), entonces puedes usar md5 con confianza.


@Mike, estoy contigo en eso, eso fue algo por lo que estaba cavando con esta pregunta, es algo sobre las funciones de hash más débiles tan fundamentalmente rotas que nunca deberían usarse.
Sam Saffron

Además de esto, si los datos o la seguridad requerida de los datos tienen una vida útil más corta que el período de crack (unos minutos en estos días iirc) MD5 está absolutamente bien. Situacionalmente útil pero aún útil es el punto.
annakata

@annakata: tenga en cuenta que también debería evitar reutilizar las claves en varios mensajes para que pueda utilizarse en esas circunstancias.
Steve Westbrook

2

Sería una buena idea echar un vistazo al algoritmo BLAKE2 .

Como se describe, es más rápido que MD5 y al menos tan seguro como SHA-3. También lo implementan varias aplicaciones de software , incluido WinRar.


Puede ser más rápido, excepto que muchas implementaciones tienen soporte de hardware, lo que hace que SHA-256 sea bastante rápido.
zaph

Estoy de acuerdo. a partir de 2019, Blake2b es el mejor hash de propósito general lanzado hasta la fecha. Significativamente más rápido que todas las otras alternativas, y no menos seguro (al menos de ninguna manera significativa), y puede ejecutarse en solo 336 bytes de ram (168 para blake2s), oh, y está optimizado para CPUs little-endian, que es El endian dominante en los sistemas actuales.
hanshenrik

0

No soy un experto en este tipo de cosas, pero me mantengo al día con la comunidad de seguridad y mucha gente considera que el hash md5 está roto. Yo diría que cuál usar depende de cuán sensibles sean los datos y la aplicación específica. Es posible que pueda escapar con un hash ligeramente menos seguro siempre que la clave sea buena y fuerte.


1
las funciones hash generalmente no usan teclas
Ethan Heilman

0

Aquí están mis sugerencias para ti:

  1. Probablemente deberías olvidarte de MD5 si anticipas ataques. Hay muchas tablas de arcoíris para ellos en línea, y se sabe que corporaciones como RIAA pueden producir secuencias con hashes equivalentes.
  2. Usa sal si puedes. Incluir la longitud del mensaje en el mensaje puede hacer que sea muy difícil hacer una colisión hash útil.
  3. Como regla general, más bits significa menos colisiones (por principio de casillero) y más lento, y tal vez más seguro (a menos que sea un genio de las matemáticas que pueda encontrar vulnerabilidades).

Vea aquí un documento que detalla un algoritmo para crear colisiones md5 en 31 segundos con una computadora de escritorio Intel P4.

http://eprint.iacr.org/2006/105


Este comentario es muy antiguo y parece bastante enterrado, pero esta parte, se sabe que los RIAA pueden producir secuencias con hashes equivalentes , saltaron hacia mí, y tengo mucha curiosidad sobre el contexto para esto. En particular, el MD5 de fuerza bruta hace 8 años fue un poco menos trivial que en 2017, por lo que deben haber tenido una buena razón.
i336_
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.