La respuesta depende de tu modelo de seguridad.
Clásicamente, una función hash criptográfica tiene tres propiedades:
- Se resiste a preimágenes : dado y , es imposible encontrar x de manera que h ( x ) = y .
- Se resiste a segundas preimágenes : dado x , no es posible encontrar x ' de manera que x x ' y h ( x ) = h ( x' ).
- Resiste a colisiones : no es factible encontrar x y x ' de manera que x x ' y h ( x ) = h ( x' ).
Para una función hash "perfecta" con una salida de bits n , la resistencia es suficiente, respectivamente, 2 n , 2 n y 2 n / 2 (independientemente de lo fuerte que sea la función, "suerte" aún funciona con una pequeña probabilidad, y eso da estos costos promedio para encontrar una preimagen, una segunda preimagen o una colisión).
Cuando trunca la salida de una función hash existente, de hecho está definiendo una nueva función hash, y como esa función hash tiene una salida más pequeña, su resistencia es correspondientemente más pequeña.
La buena pregunta es entonces: ¿en cuál de estas propiedades confías? Esto depende mucho del contexto.
Por ejemplo, supongamos que el objetivo del atacante es alterar un dato existente, sin ser detectado a través de una falta de coincidencia de la función hash. Esta es una segunda situación previa a la imagen: el atacante ve un mensaje m y trata de encontrar un mensaje modificado m ' que tenga el mismo valor. En ese caso, truncar a 10 bytes significa que todavía tiene resistencia 2 80 , un número enorme que disuadirá a todos, excepto a los atacantes más determinados o irracionales. Sin embargo, tenga en cuenta que un atacante puede tener una selección de objetivos: si ve 100 mensajes y desea modificar uno de ellos (sin preferencia sobre los que se pueden modificar), "suerte" funciona 100 veces mejor. Por lo tanto, es posible que desee un margen de seguridad adicional y mantenga, digamos, 12 o 13 bytes de salida.
Ahora, si el atacante puede inyectar su propio mensaje de apariencia inocente m , que usted valida y hash, y luego lo reemplazará con un mensaje distinto m ' con el mismo valor hash, entonces esta es una cuestión de colisiones, por lo tanto, se trabaja con la resistencia 2 n / 2 para una salida de n -bit . En ese caso, truncar la salida de la función hash es una idea bastante mala.
El curso seguro no es truncar nada. Después de todo, como escribo arriba, truncar la salida es equivalente a diseñar tu propia función hash, y, en general, es muy difícil hacerlo correctamente. SHA-1 tiene una salida de 160 bits precisamente para que obtenga "al menos 2 80 seguridad" en todos los casos. Determinar si las colisiones se aplican a su situación o no puede ser difícil.
También , recuerde que un valor de hash no crea integridad; sólo se concentra el problema. Cuando hash una parte de datos, obtienes un valor de hash, y ese valor de hash garantizará que los datos originales no cambien solo en la medida en que puedas estar seguro, a través de otros medios , de que el valor de hash sí no fue alterado. Si almacena el valor de hash junto con los datos que se han cifrado (su "entrada"), y se supone que el atacante puede alterar los datos almacenados, ¿entonces qué le impediría exactamente modificar el valor de hash? Siempre que quiera poner m ' en lugar de m en una celda de la base de datos, también puede colocar SHA-1 ( m' ) en el vecino celda, sobrescribiendo el SHA-1 ( m ) que estaba allí, y usted no sabrá nada.
Si desea utilizar valores de hash para proteger la integridad de los datos, debe asegurarse de que la integridad de los valores de hash de alguna otra manera. Las funciones de hash reducen el problema: en lugar de proteger un archivo de 1 gigabyte, "solo" necesita proteger un valor hash de 20 bytes. Pero todavía tienes que hacer algo.
La criptografía puede ayudarlo a concentrarse aún más mediante el uso de un MAC en lugar de una función hash. Con un MAC, usted tiene una clave secreta y puede usar una para millones de MAC computados sobre millones de "entradas". De nuevo, todavía tiene que hacer algo, pero ese algo es: mantener la confidencialidad de una clave única (de, por ejemplo, 128 bits) para todo el servidor.