    -- |
    -- Module      : Crypto.MAC.HMAC
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- provide the HMAC (Hash based Message Authentification Code) base algorithm.
    -- <http://en.wikipedia.org/wiki/HMAC>
    --
    module Crypto.MAC.HMAC
        ( hmac
        ) where

    import Data.ByteString (ByteString)
    import qualified Data.ByteString as B
    import Data.Bits (xor)

    -- | compute a MAC using the supplied hashing function
    --
    -- An incremental API can be found in the module "Crypto.Hash".
    --
    hmac :: (ByteString -> ByteString) -- ^ hash function
         -> Int -- ^ block size
         -> ByteString -- ^ secret
         -> ByteString -- ^ message
         -> ByteString
    hmac hashF blockSize secret msg = hashF $ B.append opad (hashF $ B.append ipad msg)
        where opad = B.map (xor 0x5c) k'
              ipad = B.map (xor 0x36) k'

              k'  = B.append kt pad
              kt  = if B.length secret > fromIntegral blockSize then hashF secret else secret
              pad = B.replicate (fromIntegral blockSize - B.length kt) 0