hs-tls/Network/TLS/MAC.hs

73 lines
2.4 KiB
Haskell
Raw Normal View History

2010-09-09 21:47:19 +00:00
module Network.TLS.MAC
( hmacMD5
, hmacSHA1
, hmacSHA256
, macSSL
, hmac
2010-09-09 21:47:19 +00:00
, prf_MD5
, prf_SHA1
2011-08-12 20:57:30 +00:00
, prf_SHA256
2010-09-09 21:47:19 +00:00
, prf_MD5SHA1
) where
import qualified Crypto.Hash.MD5 as MD5
import qualified Crypto.Hash.SHA1 as SHA1
import qualified Crypto.Hash.SHA256 as SHA256
2010-09-09 21:47:19 +00:00
import qualified Data.ByteString as B
import Data.ByteString (ByteString)
2010-09-09 21:47:19 +00:00
import Data.Bits (xor)
macSSL :: (ByteString -> ByteString) -> ByteString -> ByteString -> ByteString
macSSL f secret msg = f $! B.concat [ secret, B.replicate padlen 0x5c,
f $! B.concat [ secret, B.replicate padlen 0x36, msg ] ]
where
-- get the type of algorithm out of the digest length by using the hash fct.
padlen = if (B.length $ f B.empty) == 16 then 48 else 40
2010-09-09 21:47:19 +00:00
hmac :: (ByteString -> ByteString) -> Int -> ByteString -> ByteString -> ByteString
hmac f bl secret msg =
f $! B.append opad (f $! B.append ipad msg)
2010-09-09 21:47:19 +00:00
where
opad = B.map (xor 0x5c) k'
ipad = B.map (xor 0x36) k'
2010-09-09 21:47:19 +00:00
k' = B.append kt pad
2010-09-09 21:47:19 +00:00
where
kt = if B.length secret > fromIntegral bl then f secret else secret
pad = B.replicate (fromIntegral bl - B.length kt) 0
2010-09-09 21:47:19 +00:00
hmacMD5 :: ByteString -> ByteString -> ByteString
hmacMD5 secret msg = hmac MD5.hash 64 secret msg
2010-09-09 21:47:19 +00:00
hmacSHA1 :: ByteString -> ByteString -> ByteString
hmacSHA1 secret msg = hmac SHA1.hash 64 secret msg
2010-09-09 21:47:19 +00:00
hmacSHA256 :: ByteString -> ByteString -> ByteString
hmacSHA256 secret msg = hmac SHA256.hash 64 secret msg
2010-09-09 21:47:19 +00:00
hmacIter :: (ByteString -> ByteString -> ByteString) -> ByteString -> ByteString -> ByteString -> Int -> [ByteString]
hmacIter f secret seed aprev len =
let an = f secret aprev in
let out = f secret (B.concat [an, seed]) in
let digestsize = fromIntegral $ B.length out in
2010-09-09 21:47:19 +00:00
if digestsize >= len
then [ B.take (fromIntegral len) out ]
2010-09-09 21:47:19 +00:00
else out : hmacIter f secret seed an (len - digestsize)
prf_SHA1 :: ByteString -> ByteString -> Int -> ByteString
prf_SHA1 secret seed len = B.concat $ hmacIter hmacSHA1 secret seed seed len
2010-09-09 21:47:19 +00:00
prf_MD5 :: ByteString -> ByteString -> Int -> ByteString
prf_MD5 secret seed len = B.concat $ hmacIter hmacMD5 secret seed seed len
2010-09-09 21:47:19 +00:00
prf_MD5SHA1 :: ByteString -> ByteString -> Int -> ByteString
prf_MD5SHA1 secret seed len =
B.pack $ B.zipWith xor (prf_MD5 s1 seed len) (prf_SHA1 s2 seed len)
2010-09-09 21:47:19 +00:00
where
slen = B.length secret
s1 = B.take (slen `div` 2 + slen `mod` 2) secret
s2 = B.drop (slen `div` 2) secret
2011-08-12 20:57:30 +00:00
prf_SHA256 :: ByteString -> ByteString -> Int -> ByteString
prf_SHA256 secret seed len = B.concat $ hmacIter hmacSHA256 secret seed seed len