module Crypto.MAC.HMAC
( hmac
) where
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.Bits (xor)
hmac :: (ByteString -> ByteString)
-> Int
-> ByteString
-> ByteString
-> ByteString
hmac :: (ByteString -> ByteString)
-> Int -> ByteString -> ByteString -> ByteString
hmac hashF :: ByteString -> ByteString
hashF blockSize :: Int
blockSize secret :: ByteString
secret msg :: ByteString
msg = ByteString -> ByteString
hashF (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString -> ByteString
B.append ByteString
opad (ByteString -> ByteString
hashF (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString -> ByteString
B.append ByteString
ipad ByteString
msg)
where opad :: ByteString
opad = (Word8 -> Word8) -> ByteString -> ByteString
B.map (Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
xor 0x5c) ByteString
k'
ipad :: ByteString
ipad = (Word8 -> Word8) -> ByteString -> ByteString
B.map (Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
xor 0x36) ByteString
k'
k' :: ByteString
k' = ByteString -> ByteString -> ByteString
B.append ByteString
kt ByteString
pad
kt :: ByteString
kt = if ByteString -> Int
B.length ByteString
secret Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
blockSize then ByteString -> ByteString
hashF ByteString
secret else ByteString
secret
pad :: ByteString
pad = Int -> Word8 -> ByteString
B.replicate (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
blockSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- ByteString -> Int
B.length ByteString
kt) 0