{-# LANGUAGE OverloadedStrings #-} module Network.Sasl.ScramSha1.Functions ( xo, SHA1.hash, saltedPassword, clientKey, storedKey, serverKey, clientSignature, clientProof, serverSignature, ) where import Data.Bits import qualified Data.ByteString as BS import qualified Data.ByteString.Base64 as B64 import qualified Crypto.Hash.SHA1 as SHA1 import Network.Sasl.ScramSha1.Hmac int1 :: BS.ByteString int1 = "\0\0\0\1" xo :: BS.ByteString -> BS.ByteString -> BS.ByteString "" `xo` b2 = b2 b1 `xo` "" = b1 b1 `xo` b2 = BS.pack $ zipWith xor (BS.unpack b1) (BS.unpack b2) hi :: BS.ByteString -> BS.ByteString -> Int -> BS.ByteString hi str salt i = foldl1 xo . take i . tail . iterate (hmac SHA1.hash 64 str) $ salt `BS.append` int1 saltedPassword :: BS.ByteString -> BS.ByteString -> Int -> BS.ByteString saltedPassword = hi clientKey :: BS.ByteString -> BS.ByteString clientKey sp = hmac SHA1.hash 64 sp "Client Key" storedKey :: BS.ByteString -> BS.ByteString storedKey = SHA1.hash . clientKey clientSignature :: BS.ByteString -> BS.ByteString -> BS.ByteString clientSignature = hmac SHA1.hash 64 clientProof :: BS.ByteString -> BS.ByteString -> BS.ByteString clientProof ck am = B64.encode $ ck `xo` clientSignature (SHA1.hash ck) am serverKey :: BS.ByteString -> BS.ByteString serverKey sp = hmac SHA1.hash 64 sp "Server Key" serverSignature :: BS.ByteString -> BS.ByteString -> BS.ByteString serverSignature sk am = B64.encode $ hmac SHA1.hash 64 sk am