2012-02-29 15 views
7

Ho un elenco di percorsi file e voglio che tutti questi file vengano archiviati come hash codificato sha1 in un elenco. Dovrebbe essere il più generale possibile, in modo che i file possano essere sia di testo che di file binari. E ora le mie domande sono:Codifica SHA1 in Haskell

  1. Quali pacchetti devono essere utilizzati e perché?
  2. Quanto è coerente l'approccio? Con questo intendo: se ci potrebbero essere diversi risultati con diversi programmi utilizzando sha1 per la codifica stessa (ad esempio sha1sum)
+1

Non riesco a giudicare la qualità delle implementazioni, ma ci sono diverse implementazioni di SHA1 in pacchetti su hackage (sezione Cryptography). Con la definizione di SHA1, funziona sui byte del file, quindi se il testo o il binario non contano e tutte le implementazioni corrette danno lo stesso risultato per lo stesso file. –

risposta

18

Il pacchetto cryptohash è probabilmente il più semplice da utilizzare. Basta leggere l'input in un pigro ByteString e utilizzare la funzione hashlazy per ottenere un ByteString con l'hash risultante. Ecco un piccolo programma di esempio che puoi utilizzare per confrontare l'output con quello di 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() 

Dal momento che questa legge byte strisciamento, non personaggi, non ci dovrebbero essere problemi di codifica e dovrebbe sempre dare lo stesso risultato di sha1sum:

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

Questo funziona anche per una qualsiasi delle hash supportati da il pacchetto criptohash. Basta cambiare l'importazione ad es. Crypto.Hash.SHA256 per utilizzare un hash diverso.

L'utilizzo di ByteString pigro evita il caricamento dell'intero file in memoria in una volta, operazione importante quando si lavora con file di grandi dimensioni.