module Crypto.Hash
(
Context
, Digest
, digestFromByteString
, hashInitWith
, hashWith
, hashInit
, hashUpdates
, hashUpdate
, hashFinalize
, hashBlockSize
, hashDigestSize
, hash
, hashlazy
, module Crypto.Hash.Algorithms
) where
import Control.Monad
import Crypto.Hash.Types
import Crypto.Hash.Algorithms
import Foreign.Ptr (Ptr)
import Crypto.Internal.ByteArray (ByteArrayAccess)
import qualified Crypto.Internal.ByteArray as B
import qualified Data.ByteString.Lazy as L
hash :: (ByteArrayAccess ba, HashAlgorithm a) => ba -> Digest a
hash bs = hashFinalize $ hashUpdate hashInit bs
hashlazy :: HashAlgorithm a => L.ByteString -> Digest a
hashlazy lbs = hashFinalize $ hashUpdates hashInit (L.toChunks lbs)
hashInit :: HashAlgorithm a
=> Context a
hashInit = doInit undefined B.allocAndFreeze
where
doInit :: HashAlgorithm a => a -> (Int -> (Ptr (Context a) -> IO ()) -> B.Bytes) -> Context a
doInit alg alloc = Context $ alloc (hashInternalContextSize alg) hashInternalInit
hashUpdate :: (ByteArrayAccess ba, HashAlgorithm a) => Context a -> ba -> Context a
hashUpdate ctx b = hashUpdates ctx [b]
hashUpdates :: (HashAlgorithm a, ByteArrayAccess ba)
=> Context a
-> [ba]
-> Context a
hashUpdates c l = doUpdates (B.copyAndFreeze c)
where doUpdates :: HashAlgorithm a => ((Ptr (Context a) -> IO ()) -> B.Bytes) -> Context a
doUpdates copy = Context $ copy $ \ctx ->
mapM_ (\b -> B.withByteArray b $ \d -> hashInternalUpdate ctx d (fromIntegral $ B.length b)) l
hashFinalize :: HashAlgorithm a
=> Context a
-> Digest a
hashFinalize c = doFinalize undefined (B.copy c) (B.allocAndFreeze)
where doFinalize :: HashAlgorithm alg
=> alg
-> ((Ptr (Context alg) -> IO ()) -> IO B.Bytes)
-> (Int -> (Ptr (Digest alg) -> IO ()) -> B.Bytes)
-> Digest alg
doFinalize alg copy allocDigest =
Digest $ allocDigest (hashDigestSize alg) $ \dig ->
(void $ copy $ \ctx -> hashInternalFinalize ctx dig)
hashInitWith :: HashAlgorithm alg => alg -> Context alg
hashInitWith _ = hashInit
hashWith :: (ByteArrayAccess ba, HashAlgorithm alg) => alg -> ba -> Digest alg
hashWith _ = hash
digestFromByteString :: (HashAlgorithm a, ByteArrayAccess ba) => ba -> Maybe (Digest a)
digestFromByteString = from undefined
where
from :: (HashAlgorithm a, ByteArrayAccess ba) => a -> ba -> Maybe (Digest a)
from alg bs
| B.length bs == (hashDigestSize alg) = (Just $ Digest $ B.convert bs)
| otherwise = Nothing