2012-02-29 12 views
7

Tengo una lista de rutas de archivos y quiero que todos estos archivos se almacenen como hash codificados sha1 en una lista nuevamente. Debe ser lo más general posible, de modo que los archivos puedan ser tanto de texto como binarios. Y ahora mis preguntas son:Codificación SHA1 en Haskell

  1. ¿Qué paquetes deben usarse y por qué?
  2. ¿Qué tan consistente es el enfoque? Con esto quiero decir: si pudiera haber resultados diferentes con diferentes programas utilizando SHA1 para la codificación en sí (por ejemplo sha1sum)
+1

No puedo juzgar la calidad de las implementaciones, pero hay varias implementaciones de SHA1 en paquetes en hackage (sección Criptografía). Según la definición de SHA1, funciona en los bytes del archivo, por lo que no importa si es texto o binario, y todas las implementaciones correctas dan el mismo resultado para el mismo archivo. –

Respuesta

18

El paquete cryptohash es probablemente el más simple de usar. Simplemente lea su entrada en un perezoso 1 ByteString y use la función hashlazy para obtener una ByteString con el hash resultante. Aquí hay un pequeño programa de muestra que puede usar para comparar la salida con la de sha1sum.

import Crypto.Hash.SHA1 (hashlazy) 
import qualified Data.ByteString as Strict 
import qualified Data.ByteString.Lazy as Lazy 
import System.Process (system) 
import Text.Printf (printf) 

hashFile :: FilePath -> IO Strict.ByteString 
hashFile = fmap hashlazy . Lazy.readFile 

toHex :: Strict.ByteString -> String 
toHex bytes = Strict.unpack bytes >>= printf "%02x" 

test :: FilePath -> IO() 
test path = do 
    hashFile path >>= putStrLn . toHex 
    system $ "sha1sum " ++ path 
    return() 

Dado que este lee bytes de civil, no caracteres, no debería haber problemas de codificación y siempre debe dar el mismo resultado que sha1sum:

> test "/usr/share/dict/words" 
d6e483cb67d6de3b8cfe8f4952eb55453bb99116 
d6e483cb67d6de3b8cfe8f4952eb55453bb99116 /usr/share/dict/words 

Esto también funciona para cualquiera de los hashes con el apoyo de el paquete de cryptohash Simplemente cambie la importación a, p. Crypto.Hash.SHA256 para usar un hash diferente.

Usar ByteStrings vago evita cargar todo el archivo en la memoria a la vez, lo cual es importante cuando se trabaja con archivos de gran tamaño.