module Crypto.HMAC
( hmac
, hmac'
, MacKey(..)
) where
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import Crypto.Classes
import Data.Serialize (encode)
import Data.Bits (xor)
newtype MacKey c d = MacKey B.ByteString deriving (MacKey c d -> MacKey c d -> Bool
(MacKey c d -> MacKey c d -> Bool)
-> (MacKey c d -> MacKey c d -> Bool) -> Eq (MacKey c d)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall c d. MacKey c d -> MacKey c d -> Bool
$c== :: forall c d. MacKey c d -> MacKey c d -> Bool
== :: MacKey c d -> MacKey c d -> Bool
$c/= :: forall c d. MacKey c d -> MacKey c d -> Bool
/= :: MacKey c d -> MacKey c d -> Bool
Eq, Eq (MacKey c d)
Eq (MacKey c d) =>
(MacKey c d -> MacKey c d -> Ordering)
-> (MacKey c d -> MacKey c d -> Bool)
-> (MacKey c d -> MacKey c d -> Bool)
-> (MacKey c d -> MacKey c d -> Bool)
-> (MacKey c d -> MacKey c d -> Bool)
-> (MacKey c d -> MacKey c d -> MacKey c d)
-> (MacKey c d -> MacKey c d -> MacKey c d)
-> Ord (MacKey c d)
MacKey c d -> MacKey c d -> Bool
MacKey c d -> MacKey c d -> Ordering
MacKey c d -> MacKey c d -> MacKey c d
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall c d. Eq (MacKey c d)
forall c d. MacKey c d -> MacKey c d -> Bool
forall c d. MacKey c d -> MacKey c d -> Ordering
forall c d. MacKey c d -> MacKey c d -> MacKey c d
$ccompare :: forall c d. MacKey c d -> MacKey c d -> Ordering
compare :: MacKey c d -> MacKey c d -> Ordering
$c< :: forall c d. MacKey c d -> MacKey c d -> Bool
< :: MacKey c d -> MacKey c d -> Bool
$c<= :: forall c d. MacKey c d -> MacKey c d -> Bool
<= :: MacKey c d -> MacKey c d -> Bool
$c> :: forall c d. MacKey c d -> MacKey c d -> Bool
> :: MacKey c d -> MacKey c d -> Bool
$c>= :: forall c d. MacKey c d -> MacKey c d -> Bool
>= :: MacKey c d -> MacKey c d -> Bool
$cmax :: forall c d. MacKey c d -> MacKey c d -> MacKey c d
max :: MacKey c d -> MacKey c d -> MacKey c d
$cmin :: forall c d. MacKey c d -> MacKey c d -> MacKey c d
min :: MacKey c d -> MacKey c d -> MacKey c d
Ord, Int -> MacKey c d -> ShowS
[MacKey c d] -> ShowS
MacKey c d -> String
(Int -> MacKey c d -> ShowS)
-> (MacKey c d -> String)
-> ([MacKey c d] -> ShowS)
-> Show (MacKey c d)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall c d. Int -> MacKey c d -> ShowS
forall c d. [MacKey c d] -> ShowS
forall c d. MacKey c d -> String
$cshowsPrec :: forall c d. Int -> MacKey c d -> ShowS
showsPrec :: Int -> MacKey c d -> ShowS
$cshow :: forall c d. MacKey c d -> String
show :: MacKey c d -> String
$cshowList :: forall c d. [MacKey c d] -> ShowS
showList :: [MacKey c d] -> ShowS
Show)
hmac :: (Hash c d) => MacKey c d -> L.ByteString -> d
hmac :: forall c d. Hash c d => MacKey c d -> ByteString -> d
hmac (MacKey ByteString
k) ByteString
msg = d
res
where
res :: d
res = ByteString -> d
forall ctx d. (Hash ctx d, Hash ctx d) => ByteString -> d
hash' (ByteString -> d) -> (ByteString -> ByteString) -> ByteString -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString -> ByteString
B.append ByteString
ko (ByteString -> ByteString)
-> (ByteString -> ByteString) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> ByteString
forall a. Serialize a => a -> ByteString
encode (d -> ByteString) -> (ByteString -> d) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> d
f (ByteString -> d) -> (ByteString -> ByteString) -> ByteString -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString -> ByteString
L.append ByteString
ki (ByteString -> d) -> ByteString -> d
forall a b. (a -> b) -> a -> b
$ ByteString
msg
f :: ByteString -> d
f = d -> ByteString -> d
forall c d. Hash c d => d -> ByteString -> d
hashFunc d
res
keylen :: Int
keylen = ByteString -> Int
B.length ByteString
k
blen :: Int
blen = Tagged d Int
forall ctx d. Hash ctx d => Tagged d Int
blockLength Tagged d Int -> d -> Int
forall a b. Tagged a b -> a -> b
.::. d
res Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
8
k' :: ByteString
k' = case Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
keylen Int
blen of
Ordering
GT -> ByteString -> ByteString -> ByteString
B.append (d -> ByteString
forall a. Serialize a => a -> ByteString
encode (d -> ByteString) -> (ByteString -> d) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> d
f (ByteString -> d) -> (ByteString -> ByteString) -> ByteString -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
fc (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString
k) (Int -> Word8 -> ByteString
B.replicate (Int
blen Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Tagged d Int
forall ctx d. Hash ctx d => Tagged d Int
outputLength Tagged d Int -> d -> Int
forall a b. Tagged a b -> a -> b
.::. d
res Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
8) ) Word8
0x00)
Ordering
EQ -> ByteString
k
Ordering
LT -> ByteString -> ByteString -> ByteString
B.append ByteString
k (Int -> Word8 -> ByteString
B.replicate (Int
blen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
keylen) Word8
0x00)
ko :: ByteString
ko = (Word8 -> Word8) -> ByteString -> ByteString
B.map (Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
`xor` Word8
0x5c) ByteString
k'
ki :: ByteString
ki = ByteString -> ByteString
fc (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ (Word8 -> Word8) -> ByteString -> ByteString
B.map (Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
`xor` Word8
0x36) ByteString
k'
fc :: ByteString -> ByteString
fc = [ByteString] -> ByteString
L.fromChunks ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\ByteString
x -> [ByteString
x])
hmac' :: (Hash c d) => MacKey c d -> B.ByteString -> d
hmac' :: forall c d. Hash c d => MacKey c d -> ByteString -> d
hmac' MacKey c d
k = MacKey c d -> ByteString -> d
forall c d. Hash c d => MacKey c d -> ByteString -> d
hmac MacKey c d
k (ByteString -> d) -> (ByteString -> ByteString) -> ByteString -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
L.fromChunks ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return