module Botan.BlockCipher.Class
( BlockCipher(..)
, SecretKey(..)
, Ciphertext(..)
, LazyCiphertext(..)
, blockCipherEncryptProxy
, blockCipherDecryptProxy
, blockCipherEncryptFile
, blockCipherDecryptFile
, IncrementalBlockCipher(..)
, blockCipherEncryptFileLazy
, blockCipherDecryptFileLazy
, unsafeBlockCipherEncrypt
, unsafeBlockCipherDecrypt
, unsafeBlockCipherEncryptLazy
, unsafeBlockCipherDecryptLazy
, BlockCipher128(..)
, IncrementalBlockCipher128(..)
) where

import Botan.Prelude hiding (Ciphertext, LazyCiphertext)

import Data.Maybe
import Data.Proxy (Proxy(..))

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

import Botan.Types.Class
import Botan.RNG

-- TODO: Maybe make take Block instead of ByteString, where Block (n :: Nat) ~ ByteString | length bs == natVal n

-- NOTE: Cannot do g- / default implementation like this
-- See notes in Botan.Types.Class
-- instance (BlockCipher bc, MonadRandomIO m) => SecretKeyGen bc m where
--     newSecretKey :: m (SecretKey alg)
--     newSecretKey = _

--     newSecretKeyMaybe :: Int -> m (Maybe (SecretKey alg))
--     newSecretKeyMaybe = _

class (HasSecretKey bc, HasCiphertext bc) => BlockCipher bc where

    blockCipherEncrypt :: SecretKey bc -> ByteString -> Maybe (Ciphertext bc)
    default blockCipherEncrypt :: (IncrementalBlockCipher bc) => SecretKey bc -> ByteString -> Maybe (Ciphertext bc)
    blockCipherEncrypt SecretKey bc
k = (LazyCiphertext bc -> Ciphertext bc)
-> Maybe (LazyCiphertext bc) -> Maybe (Ciphertext bc)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap LazyCiphertext bc -> Ciphertext bc
forall alg.
HasLazyCiphertext alg =>
LazyCiphertext alg -> Ciphertext alg
toStrictCiphertext (Maybe (LazyCiphertext bc) -> Maybe (Ciphertext bc))
-> (ByteString -> Maybe (LazyCiphertext bc))
-> ByteString
-> Maybe (Ciphertext bc)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SecretKey bc -> ByteString -> Maybe (LazyCiphertext bc)
forall bc.
IncrementalBlockCipher bc =>
SecretKey bc -> ByteString -> Maybe (LazyCiphertext bc)
blockCipherEncryptLazy SecretKey bc
k (ByteString -> Maybe (LazyCiphertext bc))
-> (ByteString -> ByteString)
-> ByteString
-> Maybe (LazyCiphertext bc)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
ByteString.fromStrict

    blockCipherDecrypt :: SecretKey bc -> Ciphertext bc -> Maybe ByteString
    default blockCipherDecrypt :: (IncrementalBlockCipher bc) => SecretKey bc -> Ciphertext bc -> Maybe ByteString
    blockCipherDecrypt SecretKey bc
k = (ByteString -> ByteString) -> Maybe ByteString -> Maybe ByteString
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> ByteString
ByteString.toStrict (Maybe ByteString -> Maybe ByteString)
-> (Ciphertext bc -> Maybe ByteString)
-> Ciphertext bc
-> Maybe ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SecretKey bc -> LazyCiphertext bc -> Maybe ByteString
forall bc.
IncrementalBlockCipher bc =>
SecretKey bc -> LazyCiphertext bc -> Maybe ByteString
blockCipherDecryptLazy SecretKey bc
k (LazyCiphertext bc -> Maybe ByteString)
-> (Ciphertext bc -> LazyCiphertext bc)
-> Ciphertext bc
-> Maybe ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ciphertext bc -> LazyCiphertext bc
forall alg.
HasLazyCiphertext alg =>
Ciphertext alg -> LazyCiphertext alg
fromStrictCiphertext

blockCipherEncryptProxy :: (BlockCipher bc) => Proxy bc -> SecretKey bc -> ByteString -> Maybe (Ciphertext bc)
blockCipherEncryptProxy :: forall bc.
BlockCipher bc =>
Proxy bc -> SecretKey bc -> ByteString -> Maybe (Ciphertext bc)
blockCipherEncryptProxy Proxy bc
_ = SecretKey bc -> ByteString -> Maybe (Ciphertext bc)
forall bc.
BlockCipher bc =>
SecretKey bc -> ByteString -> Maybe (Ciphertext bc)
blockCipherEncrypt

blockCipherDecryptProxy :: BlockCipher bc => Proxy bc -> SecretKey bc -> Ciphertext bc -> Maybe ByteString
blockCipherDecryptProxy :: forall bc.
BlockCipher bc =>
Proxy bc -> SecretKey bc -> Ciphertext bc -> Maybe ByteString
blockCipherDecryptProxy Proxy bc
_ = SecretKey bc -> Ciphertext bc -> Maybe ByteString
forall bc.
BlockCipher bc =>
SecretKey bc -> Ciphertext bc -> Maybe ByteString
blockCipherDecrypt

blockCipherEncryptFile :: (BlockCipher bc, MonadIO m) => SecretKey bc -> FilePath -> m (Maybe (Ciphertext bc))
blockCipherEncryptFile :: forall bc (m :: * -> *).
(BlockCipher bc, MonadIO m) =>
SecretKey bc -> FilePath -> m (Maybe (Ciphertext bc))
blockCipherEncryptFile SecretKey bc
k FilePath
fp = SecretKey bc -> ByteString -> Maybe (Ciphertext bc)
forall bc.
BlockCipher bc =>
SecretKey bc -> ByteString -> Maybe (Ciphertext bc)
blockCipherEncrypt SecretKey bc
k (ByteString -> Maybe (Ciphertext bc))
-> m ByteString -> m (Maybe (Ciphertext bc))
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)

blockCipherDecryptFile :: (BlockCipher bc, MonadIO m) => SecretKey bc -> FilePath -> m (Maybe ByteString)
blockCipherDecryptFile :: forall bc (m :: * -> *).
(BlockCipher bc, MonadIO m) =>
SecretKey bc -> FilePath -> m (Maybe ByteString)
blockCipherDecryptFile SecretKey bc
k FilePath
fp = SecretKey bc -> Ciphertext bc -> Maybe ByteString
forall bc.
BlockCipher bc =>
SecretKey bc -> Ciphertext bc -> Maybe ByteString
blockCipherDecrypt SecretKey bc
k (Ciphertext bc -> Maybe ByteString)
-> (ByteString -> Ciphertext bc) -> ByteString -> Maybe ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Ciphertext bc
forall a. Encodable a => ByteString -> a
unsafeDecode (ByteString -> Maybe ByteString)
-> m ByteString -> m (Maybe ByteString)
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 (BlockCipher bc, HasLazyCiphertext bc) => IncrementalBlockCipher bc where
    blockCipherEncryptLazy :: SecretKey bc -> Lazy.ByteString -> Maybe (LazyCiphertext bc)
    blockCipherDecryptLazy :: SecretKey bc -> LazyCiphertext bc -> Maybe Lazy.ByteString

blockCipherEncryptFileLazy :: (IncrementalBlockCipher bc, MonadIO m) => SecretKey bc -> FilePath -> m (Maybe (LazyCiphertext bc))
blockCipherEncryptFileLazy :: forall bc (m :: * -> *).
(IncrementalBlockCipher bc, MonadIO m) =>
SecretKey bc -> FilePath -> m (Maybe (LazyCiphertext bc))
blockCipherEncryptFileLazy SecretKey bc
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 :: Maybe (LazyCiphertext bc)
d = SecretKey bc -> ByteString -> Maybe (LazyCiphertext bc)
forall bc.
IncrementalBlockCipher bc =>
SecretKey bc -> ByteString -> Maybe (LazyCiphertext bc)
blockCipherEncryptLazy SecretKey bc
k ByteString
bs
        in Maybe (LazyCiphertext bc)
d Maybe (LazyCiphertext bc)
-> m (Maybe (LazyCiphertext bc)) -> m (Maybe (LazyCiphertext bc))
forall a b. a -> b -> b
`seq` Maybe (LazyCiphertext bc) -> m (Maybe (LazyCiphertext bc))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (LazyCiphertext bc)
d

blockCipherDecryptFileLazy :: (IncrementalBlockCipher bc, MonadIO m) => SecretKey bc -> FilePath -> m (Maybe Lazy.ByteString)
blockCipherDecryptFileLazy :: forall bc (m :: * -> *).
(IncrementalBlockCipher bc, MonadIO m) =>
SecretKey bc -> FilePath -> m (Maybe ByteString)
blockCipherDecryptFileLazy SecretKey bc
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 :: Maybe ByteString
d = SecretKey bc -> LazyCiphertext bc -> Maybe ByteString
forall bc.
IncrementalBlockCipher bc =>
SecretKey bc -> LazyCiphertext bc -> Maybe ByteString
blockCipherDecryptLazy SecretKey bc
k (ByteString -> LazyCiphertext bc
forall a. LazyEncodable a => ByteString -> a
unsafeDecodeLazy ByteString
bs)
        in Maybe ByteString
d Maybe ByteString -> m (Maybe ByteString) -> m (Maybe ByteString)
forall a b. a -> b -> b
`seq` Maybe ByteString -> m (Maybe ByteString)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ByteString
d

unsafeBlockCipherEncrypt :: (BlockCipher bc) => SecretKey bc -> ByteString -> Ciphertext bc
unsafeBlockCipherEncrypt :: forall bc.
BlockCipher bc =>
SecretKey bc -> ByteString -> Ciphertext bc
unsafeBlockCipherEncrypt SecretKey bc
k ByteString
bs = Maybe (Ciphertext bc) -> Ciphertext bc
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (Ciphertext bc) -> Ciphertext bc)
-> Maybe (Ciphertext bc) -> Ciphertext bc
forall a b. (a -> b) -> a -> b
$ SecretKey bc -> ByteString -> Maybe (Ciphertext bc)
forall bc.
BlockCipher bc =>
SecretKey bc -> ByteString -> Maybe (Ciphertext bc)
blockCipherEncrypt SecretKey bc
k ByteString
bs

unsafeBlockCipherDecrypt :: (BlockCipher bc) => SecretKey bc -> Ciphertext bc -> ByteString
unsafeBlockCipherDecrypt :: forall bc.
BlockCipher bc =>
SecretKey bc -> Ciphertext bc -> ByteString
unsafeBlockCipherDecrypt SecretKey bc
k Ciphertext bc
ct = Maybe ByteString -> ByteString
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe ByteString -> ByteString) -> Maybe ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ SecretKey bc -> Ciphertext bc -> Maybe ByteString
forall bc.
BlockCipher bc =>
SecretKey bc -> Ciphertext bc -> Maybe ByteString
blockCipherDecrypt SecretKey bc
k Ciphertext bc
ct

unsafeBlockCipherEncryptLazy :: (IncrementalBlockCipher bc) => SecretKey bc -> Lazy.ByteString -> LazyCiphertext bc
unsafeBlockCipherEncryptLazy :: forall bc.
IncrementalBlockCipher bc =>
SecretKey bc -> ByteString -> LazyCiphertext bc
unsafeBlockCipherEncryptLazy SecretKey bc
k ByteString
lbs = Maybe (LazyCiphertext bc) -> LazyCiphertext bc
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (LazyCiphertext bc) -> LazyCiphertext bc)
-> Maybe (LazyCiphertext bc) -> LazyCiphertext bc
forall a b. (a -> b) -> a -> b
$ SecretKey bc -> ByteString -> Maybe (LazyCiphertext bc)
forall bc.
IncrementalBlockCipher bc =>
SecretKey bc -> ByteString -> Maybe (LazyCiphertext bc)
blockCipherEncryptLazy SecretKey bc
k ByteString
lbs

unsafeBlockCipherDecryptLazy :: (IncrementalBlockCipher bc) => SecretKey bc -> LazyCiphertext bc -> Lazy.ByteString
unsafeBlockCipherDecryptLazy :: forall bc.
IncrementalBlockCipher bc =>
SecretKey bc -> LazyCiphertext bc -> ByteString
unsafeBlockCipherDecryptLazy SecretKey bc
k LazyCiphertext bc
lct = Maybe ByteString -> ByteString
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe ByteString -> ByteString) -> Maybe ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ SecretKey bc -> LazyCiphertext bc -> Maybe ByteString
forall bc.
IncrementalBlockCipher bc =>
SecretKey bc -> LazyCiphertext bc -> Maybe ByteString
blockCipherDecryptLazy SecretKey bc
k LazyCiphertext bc
lct

class (BlockCipher bc) => BlockCipher128 bc where
-- {-# WARNING BlockCipher128 "This is a temporary typeclass to restrict types requiring a block size of 128 bits; the BlockSize API will change in the future" #-}
class (IncrementalBlockCipher bc) => IncrementalBlockCipher128 bc where
-- {-# WARNING IncrementalBlockCipher128 "This is a temporary typeclass to restrict types requiring a block size of 128 bits; the BlockSize API will change in the future" #-}