module Botan.MAC.Class
( MAC(..)
, MACKey(..)
, MACAuth(..)
, macProxy
, macFile
, IncrementalMAC(..)
, macFileLazy
) where

import Botan.Prelude

import Data.Proxy (Proxy(..))

import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Lazy as Lazy

data family MACKey mac
data family MACAuth mac

class MAC mac where

    -- HACKY:
    -- witness :: mac

    mac :: MACKey mac -> ByteString -> MACAuth mac
    default mac :: (IncrementalMAC mac) => MACKey mac -> ByteString -> MACAuth mac
    mac MACKey mac
k = MACKey mac -> ByteString -> MACAuth mac
forall mac.
IncrementalMAC mac =>
MACKey mac -> ByteString -> MACAuth mac
macLazy MACKey mac
k (ByteString -> MACAuth mac)
-> (ByteString -> ByteString) -> ByteString -> MACAuth mac
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
ByteString.fromStrict

    -- verifyMAC :: MACKey mac -> ByteString -> MACAuth mac -> Bool
    -- verifyMAC k bs d = mac k bs == d

macProxy :: (MAC mac) => Proxy mac -> MACKey mac -> ByteString -> MACAuth mac
macProxy :: forall mac.
MAC mac =>
Proxy mac -> MACKey mac -> ByteString -> MACAuth mac
macProxy Proxy mac
_ = MACKey mac -> ByteString -> MACAuth mac
forall mac. MAC mac => MACKey mac -> ByteString -> MACAuth mac
mac

macFile :: (MAC mac, MonadIO m) => MACKey mac -> FilePath -> m (MACAuth mac)
macFile :: forall mac (m :: * -> *).
(MAC mac, MonadIO m) =>
MACKey mac -> FilePath -> m (MACAuth mac)
macFile MACKey mac
k FilePath
fp = MACKey mac -> ByteString -> MACAuth mac
forall mac. MAC mac => MACKey mac -> ByteString -> MACAuth mac
mac MACKey mac
k (ByteString -> MACAuth mac) -> m ByteString -> m (MACAuth mac)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO ByteString -> m ByteString
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO ByteString
ByteString.readFile FilePath
fp)

class (MAC mac) => IncrementalMAC mac where
    macLazy :: MACKey mac -> Lazy.ByteString -> MACAuth mac

macFileLazy :: (IncrementalMAC mac, MonadIO m) => MACKey mac -> FilePath -> m (MACAuth mac)
macFileLazy :: forall mac (m :: * -> *).
(IncrementalMAC mac, MonadIO m) =>
MACKey mac -> FilePath -> m (MACAuth mac)
macFileLazy MACKey mac
k FilePath
fp = do
    ByteString
bs <- IO ByteString -> m ByteString
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ByteString -> m ByteString) -> IO ByteString -> m ByteString
forall a b. (a -> b) -> a -> b
$ FilePath -> IO ByteString
Lazy.readFile FilePath
fp
    -- Seq is probably unnecessary
    let d :: MACAuth mac
d = MACKey mac -> ByteString -> MACAuth mac
forall mac.
IncrementalMAC mac =>
MACKey mac -> ByteString -> MACAuth mac
macLazy MACKey mac
k ByteString
bs
        in MACAuth mac
d MACAuth mac -> m (MACAuth mac) -> m (MACAuth mac)
forall a b. a -> b -> b
`seq` MACAuth mac -> m (MACAuth mac)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return MACAuth mac
d