-- | Simple abstraction for message digests
module Digest
( Digest
, digest
)
where
import Data.Char
import Data.Word
import Control.Monad.State
import Foreign.Ptr
import qualified Data.ByteString as B
import Data.ByteString.Unsafe
import qualified Data.ByteString.Lazy as L
import qualified OpenSSL.Digest as SSL
-- Consider newtyping this
type Digest = String
digest :: L.ByteString -> IO Digest
digest bs = do
upack <- digestLBS SSL.SHA1 bs
return $ map (chr . fromIntegral) upack
digestLBS :: SSL.MessageDigest -> L.ByteString -> IO [Word8]
digestLBS mdType xs =
SSL.mkDigest mdType $ evalStateT (updateLBS xs >> SSL.final)
updateBS :: B.ByteString -> SSL.Digest ()
updateBS bs = do
SSL.DST ctx <- get
liftIO $ unsafeUseAsCStringLen bs $
\(ptr, len) -> SSL.digestUpdate ctx (castPtr ptr) (fromIntegral len)
return ()
updateLBS :: L.ByteString -> SSL.Digest ()
updateLBS lbs = mapM_ updateBS $ L.toChunks lbs