-- | A pure interface to SHA2
module Codec.Digest.SHA(
  Length(..), hash, hmac,
  showBSasHex
) where

import Codec.Digest.SHA.Monad
import qualified Data.ByteString as B
import Data.Bits(xor)

-- | Plain SHA2
hash :: Hashable a => Length -> a -> B.ByteString
hash len bs = snd $ runSHA len (update bs)

lenBytes :: Num a => Length -> a
lenBytes SHA256 = 32
lenBytes SHA384 = 48
lenBytes SHA512 = 64

fixkey :: B.ByteString -> Length -> B.ByteString
fixkey k (lenBytes -> len) = if B.length k >= len
                            then B.take len k
                            else B.concat [k,(B.replicate (len - B.length k) 0)]

-- | SHA2-based HMAC, see http://en.wikipedia.org/wiki/HMAC
--
-- If you're doing encryption and want to prevent attackers from
-- changing your messages, you probably want this.
hmac :: Hashable a 
       => Length -- ^ Desired size of the HMAC
       -> B.ByteString -- ^ The shared secret key to use
       -> a -- ^ Message to hash
       -> B.ByteString
hmac len key' msg = hash len $ B.concat [opad,ihash]
  where
    ihash = snd $ runSHA len $ update ipad >> update msg
    opad = B.map (xor 0x5c) key
    ipad = B.map (xor 0x36) key
    key = fixkey key' len