    {-# LANGUAGE PackageImports #-}

    -- |
    -- Module      : Crypto.Hash.MD4
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- A module containing MD4 bindings
    --
    module Crypto.Hash.MD4
        ( Ctx(..)

        -- * Incremental hashing Functions
        , init     -- :: Ctx
        , update   -- :: Ctx -> ByteString -> Ctx
        , updates  -- :: Ctx -> [ByteString] -> Ctx
        , finalize -- :: Ctx -> ByteString

        -- * Single Pass hashing
        , hash     -- :: ByteString -> ByteString
        , hashlazy -- :: ByteString -> ByteString
        ) where

    import Prelude hiding (init)
    import qualified Data.ByteString.Lazy as L
    import Data.ByteString (ByteString)
    import Crypto.Hash.Internal (digestToByteString, digestToByteStringWitness)

    import qualified "cryptonite" Crypto.Hash as H

    -- | MD4 Context
    newtype Ctx = Ctx (H.Context H.MD4)

    -- | init a context
    init :: Ctx
    init :: Ctx
    init = Context MD4 -> Ctx
    Ctx Context MD4
    forall a. HashAlgorithm a => Context a
    H.hashInit

    -- | update a context with a bytestring
    update :: Ctx -> ByteString -> Ctx
    update :: Ctx -> ByteString -> Ctx
    update (Ctx Context MD4
    ctx) ByteString
    d = Context MD4 -> Ctx
    Ctx (Context MD4 -> Ctx) -> Context MD4 -> Ctx
    forall a b. (a -> b) -> a -> b
    $ Context MD4 -> ByteString -> Context MD4
    forall ba a.
    (ByteArrayAccess ba, HashAlgorithm a) =>
    Context a -> ba -> Context a
    H.hashUpdate Context MD4
    ctx ByteString
    d

    -- | updates a context with multiples bytestring
    updates :: Ctx -> [ByteString] -> Ctx
    updates :: Ctx -> [ByteString] -> Ctx
    updates (Ctx Context MD4
    ctx) [ByteString]
    d =
        Context MD4 -> Ctx
    Ctx (Context MD4 -> Ctx) -> Context MD4 -> Ctx
    forall a b. (a -> b) -> a -> b
    $ Context MD4 -> [ByteString] -> Context MD4
    forall a ba.
    (HashAlgorithm a, ByteArrayAccess ba) =>
    Context a -> [ba] -> Context a
    H.hashUpdates Context MD4
    ctx [ByteString]
    d

    -- | finalize the context into a digest bytestring
    finalize :: Ctx -> ByteString
    finalize :: Ctx -> ByteString
    finalize (Ctx Context MD4
    ctx) = Digest MD4 -> ByteString
    forall h. HashAlgorithm h => Digest h -> ByteString
    digestToByteString (Digest MD4 -> ByteString) -> Digest MD4 -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Context MD4 -> Digest MD4
    forall a. HashAlgorithm a => Context a -> Digest a
    H.hashFinalize Context MD4
    ctx

    -- | hash a strict bytestring into a digest bytestring
    hash :: ByteString -> ByteString
    hash :: ByteString -> ByteString
    hash ByteString
    d = MD4 -> Digest MD4 -> ByteString
    forall h. HashAlgorithm h => h -> Digest h -> ByteString
    digestToByteStringWitness MD4
    H.MD4 (Digest MD4 -> ByteString) -> Digest MD4 -> ByteString
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Digest MD4
    forall ba a.
    (ByteArrayAccess ba, HashAlgorithm a) =>
    ba -> Digest a
    H.hash ByteString
    d

    -- | hash a lazy bytestring into a digest bytestring
    hashlazy :: L.ByteString -> ByteString
    hashlazy :: ByteString -> ByteString
    hashlazy ByteString
    l = MD4 -> Digest MD4 -> ByteString
    forall h. HashAlgorithm h => h -> Digest h -> ByteString
    digestToByteStringWitness MD4
    H.MD4 (Digest MD4 -> ByteString) -> Digest MD4 -> ByteString
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Digest MD4
    forall a. HashAlgorithm a => ByteString -> Digest a
    H.hashlazy ByteString
    l