packages feed

haskdeep-0.1.0.0: src/HaskDeep/ComputationMode.hs

{-# LANGUAGE OverloadedStrings #-}
-- |
-- Module      :  HaskDeep.Computation
-- Copyright   :  Mauro Taraborelli 2012
-- License     :  BSD3
--
-- Maintainer  :  maurotaraborelli@gmail.com
-- Stability   :  experimental
-- Portability :  unknown
--
-- Computes hashes traversing recursively through a directory structure.
-- Uses a list of known hashes to audit a set of files.
--
-- Internal module.

module HaskDeep.ComputationMode
    (
     -- * Computation modes
     ComputationMode (..)
    ,md5hash
    ,sha1hash
    ,sha256hash
    ,skein512hash
    )
where

import           Data.Bits ((.&.), shiftR)

import           Crypto.Hash.MD5 (MD5)
import           Crypto.Hash.SHA1 (SHA1)
import           Crypto.Hash.SHA256 (SHA256)
import           Crypto.Hash.Skein512 (Skein512)
import           Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.Serialize as S
import qualified Data.Text as T

-- | Algorithm to compute hash.
data ComputationMode a = ComputationMode
    { symbol         :: T.Text           -- ^ Computation mode symbol
    , runComputation :: a -> ByteString  -- ^ Computation function
    }

-- | MD5 computation.
md5hash  :: ComputationMode MD5
md5hash  = ComputationMode "md5" (toHex . S.encode)

-- | SHA1 computation.
sha1hash :: ComputationMode SHA1
sha1hash = ComputationMode "sha1" (toHex . S.encode)

-- | SHA256 computation.
sha256hash :: ComputationMode SHA256
sha256hash = ComputationMode "sha256" (toHex . S.encode)

-- | Skein512 computation.
skein512hash :: ComputationMode Skein512
skein512hash = ComputationMode "skein512" (toHex . S.encode)

-- Only with ByteString 0.10
--toHex :: ByteString -> ByteString
--toHex = BS.concat . BL.toChunks . BB.toLazyByteString . BA.byteStringHexFixed

-- Taken from
-- http://stackoverflow.com/questions/10099921/efficiently-turn-a-bytestring-into-a-hex-representation
toHex :: ByteString -> ByteString
toHex bs0 =
    fst $ BS.unfoldrN (BS.length bs0 * 2) go (Left bs0)
  where
    go (Left bs) =
        case BS.uncons bs of
            Nothing -> Nothing
            Just (w, bs') ->
                let w1 = w `shiftR` 4
                    w2 = w .&. 15
                    c1 = toC w1
                    c2 = toC w2
                 in Just (c1, Right (c2, bs'))
    go (Right (c, bs)) = Just (c, Left bs)

    toC w
        | w < 10 = w + 48
        | otherwise = w + 87