{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Simplex.Messaging.Crypto.File
( CryptoFile (..),
CryptoFileArgs (..),
CryptoFileHandle (..),
FTCryptoError (..),
Simplex.Messaging.Crypto.File.readFile,
Simplex.Messaging.Crypto.File.writeFile,
withFile,
hPut,
hPutTag,
hGet,
hGetTag,
plain,
randomArgs,
getFileContentsSize,
)
where
import Control.Exception
import Control.Monad
import Control.Monad.Except
import Control.Monad.Trans.Except
import Crypto.Random (ChaChaDRG)
import qualified Data.Aeson.TH as J
import qualified Data.ByteArray as BA
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy as LB
import Data.List.NonEmpty (NonEmpty (..))
import Data.Maybe (isJust)
import qualified Simplex.Messaging.Crypto as C
import Simplex.Messaging.Crypto.Lazy (LazyByteString)
import qualified Simplex.Messaging.Crypto.Lazy as LC
import Simplex.Messaging.Parsers (defaultJSON)
import Simplex.Messaging.Util (liftEitherWith)
import System.Directory (getFileSize)
import UnliftIO (Handle, IOMode (..), liftIO)
import qualified UnliftIO as IO
import UnliftIO.STM
data CryptoFile = CryptoFile {CryptoFile -> FilePath
filePath :: FilePath, CryptoFile -> Maybe CryptoFileArgs
cryptoArgs :: Maybe CryptoFileArgs}
deriving (CryptoFile -> CryptoFile -> Bool
(CryptoFile -> CryptoFile -> Bool)
-> (CryptoFile -> CryptoFile -> Bool) -> Eq CryptoFile
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CryptoFile -> CryptoFile -> Bool
== :: CryptoFile -> CryptoFile -> Bool
$c/= :: CryptoFile -> CryptoFile -> Bool
/= :: CryptoFile -> CryptoFile -> Bool
Eq, Int -> CryptoFile -> ShowS
[CryptoFile] -> ShowS
CryptoFile -> FilePath
(Int -> CryptoFile -> ShowS)
-> (CryptoFile -> FilePath)
-> ([CryptoFile] -> ShowS)
-> Show CryptoFile
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CryptoFile -> ShowS
showsPrec :: Int -> CryptoFile -> ShowS
$cshow :: CryptoFile -> FilePath
show :: CryptoFile -> FilePath
$cshowList :: [CryptoFile] -> ShowS
showList :: [CryptoFile] -> ShowS
Show)
data CryptoFileArgs = CFArgs {CryptoFileArgs -> SbKey
fileKey :: C.SbKey, CryptoFileArgs -> CbNonce
fileNonce :: C.CbNonce}
deriving (CryptoFileArgs -> CryptoFileArgs -> Bool
(CryptoFileArgs -> CryptoFileArgs -> Bool)
-> (CryptoFileArgs -> CryptoFileArgs -> Bool) -> Eq CryptoFileArgs
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CryptoFileArgs -> CryptoFileArgs -> Bool
== :: CryptoFileArgs -> CryptoFileArgs -> Bool
$c/= :: CryptoFileArgs -> CryptoFileArgs -> Bool
/= :: CryptoFileArgs -> CryptoFileArgs -> Bool
Eq, Int -> CryptoFileArgs -> ShowS
[CryptoFileArgs] -> ShowS
CryptoFileArgs -> FilePath
(Int -> CryptoFileArgs -> ShowS)
-> (CryptoFileArgs -> FilePath)
-> ([CryptoFileArgs] -> ShowS)
-> Show CryptoFileArgs
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CryptoFileArgs -> ShowS
showsPrec :: Int -> CryptoFileArgs -> ShowS
$cshow :: CryptoFileArgs -> FilePath
show :: CryptoFileArgs -> FilePath
$cshowList :: [CryptoFileArgs] -> ShowS
showList :: [CryptoFileArgs] -> ShowS
Show)
data CryptoFileHandle = CFHandle Handle (Maybe (TVar LC.SbState))
readFile :: CryptoFile -> ExceptT FTCryptoError IO LazyByteString
readFile :: CryptoFile -> ExceptT FTCryptoError IO LazyByteString
readFile (CryptoFile FilePath
path Maybe CryptoFileArgs
cfArgs) = do
LazyByteString
s <- IO LazyByteString -> ExceptT FTCryptoError IO LazyByteString
forall a. IO a -> ExceptT FTCryptoError IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO LazyByteString -> ExceptT FTCryptoError IO LazyByteString)
-> IO LazyByteString -> ExceptT FTCryptoError IO LazyByteString
forall a b. (a -> b) -> a -> b
$ FilePath -> IO LazyByteString
LB.readFile FilePath
path
case Maybe CryptoFileArgs
cfArgs of
Just (CFArgs (C.SbKey ByteString
key) (C.CbNonce ByteString
nonce)) -> do
let len :: Int64
len = LazyByteString -> Int64
LB.length LazyByteString
s Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
C.authTagSize
Bool -> ExceptT FTCryptoError IO () -> ExceptT FTCryptoError IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int64
len Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0) (ExceptT FTCryptoError IO () -> ExceptT FTCryptoError IO ())
-> ExceptT FTCryptoError IO () -> ExceptT FTCryptoError IO ()
forall a b. (a -> b) -> a -> b
$ FTCryptoError -> ExceptT FTCryptoError IO ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE FTCryptoError
FTCEInvalidFileSize
let (LazyByteString
s', LazyByteString
tag') = Int64 -> LazyByteString -> (LazyByteString, LazyByteString)
LB.splitAt Int64
len LazyByteString
s
(ByteString
tag :| [ByteString]
cs) <- (CryptoError -> FTCryptoError)
-> Either CryptoError (NonEmpty ByteString)
-> ExceptT FTCryptoError IO (NonEmpty ByteString)
forall (m :: * -> *) e e' a.
MonadIO m =>
(e -> e') -> Either e a -> ExceptT e' m a
liftEitherWith CryptoError -> FTCryptoError
FTCECryptoError (Either CryptoError (NonEmpty ByteString)
-> ExceptT FTCryptoError IO (NonEmpty ByteString))
-> Either CryptoError (NonEmpty ByteString)
-> ExceptT FTCryptoError IO (NonEmpty ByteString)
forall a b. (a -> b) -> a -> b
$ (SbState -> ByteString -> (ByteString, SbState))
-> ByteString
-> ByteString
-> LazyByteString
-> Either CryptoError (NonEmpty ByteString)
forall key.
ByteArrayAccess key =>
(SbState -> ByteString -> (ByteString, SbState))
-> key
-> ByteString
-> LazyByteString
-> Either CryptoError (NonEmpty ByteString)
LC.secretBox SbState -> ByteString -> (ByteString, SbState)
LC.sbDecryptChunk ByteString
key ByteString
nonce LazyByteString
s'
Bool -> ExceptT FTCryptoError IO () -> ExceptT FTCryptoError IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> ByteString -> Bool
forall bs1 bs2.
(ByteArrayAccess bs1, ByteArrayAccess bs2) =>
bs1 -> bs2 -> Bool
BA.constEq (LazyByteString -> ByteString
LB.toStrict LazyByteString
tag') ByteString
tag) (ExceptT FTCryptoError IO () -> ExceptT FTCryptoError IO ())
-> ExceptT FTCryptoError IO () -> ExceptT FTCryptoError IO ()
forall a b. (a -> b) -> a -> b
$ FTCryptoError -> ExceptT FTCryptoError IO ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE FTCryptoError
FTCEInvalidAuthTag
LazyByteString -> ExceptT FTCryptoError IO LazyByteString
forall a. a -> ExceptT FTCryptoError IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (LazyByteString -> ExceptT FTCryptoError IO LazyByteString)
-> LazyByteString -> ExceptT FTCryptoError IO LazyByteString
forall a b. (a -> b) -> a -> b
$ [ByteString] -> LazyByteString
LB.fromChunks [ByteString]
cs
Maybe CryptoFileArgs
Nothing -> LazyByteString -> ExceptT FTCryptoError IO LazyByteString
forall a. a -> ExceptT FTCryptoError IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure LazyByteString
s
writeFile :: CryptoFile -> LazyByteString -> ExceptT FTCryptoError IO ()
writeFile :: CryptoFile -> LazyByteString -> ExceptT FTCryptoError IO ()
writeFile (CryptoFile FilePath
path Maybe CryptoFileArgs
cfArgs) LazyByteString
s = do
LazyByteString
s' <- case Maybe CryptoFileArgs
cfArgs of
Just (CFArgs (C.SbKey ByteString
key) (C.CbNonce ByteString
nonce)) ->
(CryptoError -> FTCryptoError)
-> Either CryptoError LazyByteString
-> ExceptT FTCryptoError IO LazyByteString
forall (m :: * -> *) e e' a.
MonadIO m =>
(e -> e') -> Either e a -> ExceptT e' m a
liftEitherWith CryptoError -> FTCryptoError
FTCECryptoError (Either CryptoError LazyByteString
-> ExceptT FTCryptoError IO LazyByteString)
-> Either CryptoError LazyByteString
-> ExceptT FTCryptoError IO LazyByteString
forall a b. (a -> b) -> a -> b
$ [ByteString] -> LazyByteString
LB.fromChunks ([ByteString] -> LazyByteString)
-> Either CryptoError [ByteString]
-> Either CryptoError LazyByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (SbState -> ByteString -> (ByteString, SbState))
-> ByteString
-> ByteString
-> LazyByteString
-> Either CryptoError [ByteString]
forall key.
ByteArrayAccess key =>
(SbState -> ByteString -> (ByteString, SbState))
-> key
-> ByteString
-> LazyByteString
-> Either CryptoError [ByteString]
LC.secretBoxTailTag SbState -> ByteString -> (ByteString, SbState)
LC.sbEncryptChunk ByteString
key ByteString
nonce LazyByteString
s
Maybe CryptoFileArgs
Nothing -> LazyByteString -> ExceptT FTCryptoError IO LazyByteString
forall a. a -> ExceptT FTCryptoError IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure LazyByteString
s
IO () -> ExceptT FTCryptoError IO ()
forall a. IO a -> ExceptT FTCryptoError IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT FTCryptoError IO ())
-> IO () -> ExceptT FTCryptoError IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> LazyByteString -> IO ()
LB.writeFile FilePath
path LazyByteString
s'
withFile :: CryptoFile -> IOMode -> (CryptoFileHandle -> ExceptT FTCryptoError IO a) -> ExceptT FTCryptoError IO a
withFile :: forall a.
CryptoFile
-> IOMode
-> (CryptoFileHandle -> ExceptT FTCryptoError IO a)
-> ExceptT FTCryptoError IO a
withFile (CryptoFile FilePath
path Maybe CryptoFileArgs
cfArgs) IOMode
mode CryptoFileHandle -> ExceptT FTCryptoError IO a
action = do
Maybe (TVar SbState)
sb <- Maybe CryptoFileArgs
-> (CryptoFileArgs -> ExceptT FTCryptoError IO (TVar SbState))
-> ExceptT FTCryptoError IO (Maybe (TVar SbState))
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM Maybe CryptoFileArgs
cfArgs ((CryptoFileArgs -> ExceptT FTCryptoError IO (TVar SbState))
-> ExceptT FTCryptoError IO (Maybe (TVar SbState)))
-> (CryptoFileArgs -> ExceptT FTCryptoError IO (TVar SbState))
-> ExceptT FTCryptoError IO (Maybe (TVar SbState))
forall a b. (a -> b) -> a -> b
$ \(CFArgs SbKey
key CbNonce
nonce) ->
(CryptoError -> FTCryptoError)
-> Either CryptoError SbState -> ExceptT FTCryptoError IO SbState
forall (m :: * -> *) e e' a.
MonadIO m =>
(e -> e') -> Either e a -> ExceptT e' m a
liftEitherWith CryptoError -> FTCryptoError
FTCECryptoError (SbKey -> CbNonce -> Either CryptoError SbState
LC.sbInit SbKey
key CbNonce
nonce) ExceptT FTCryptoError IO SbState
-> (SbState -> ExceptT FTCryptoError IO (TVar SbState))
-> ExceptT FTCryptoError IO (TVar SbState)
forall a b.
ExceptT FTCryptoError IO a
-> (a -> ExceptT FTCryptoError IO b) -> ExceptT FTCryptoError IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= SbState -> ExceptT FTCryptoError IO (TVar SbState)
forall (m :: * -> *) a. MonadIO m => a -> m (TVar a)
newTVarIO
IO (Either FTCryptoError a) -> ExceptT FTCryptoError IO a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (IO (Either FTCryptoError a) -> ExceptT FTCryptoError IO a)
-> ((Handle -> IO (Either FTCryptoError a))
-> IO (Either FTCryptoError a))
-> (Handle -> IO (Either FTCryptoError a))
-> ExceptT FTCryptoError IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath
-> IOMode
-> (Handle -> IO (Either FTCryptoError a))
-> IO (Either FTCryptoError a)
forall (m :: * -> *) a.
MonadUnliftIO m =>
FilePath -> IOMode -> (Handle -> m a) -> m a
IO.withFile FilePath
path IOMode
mode ((Handle -> IO (Either FTCryptoError a))
-> ExceptT FTCryptoError IO a)
-> (Handle -> IO (Either FTCryptoError a))
-> ExceptT FTCryptoError IO a
forall a b. (a -> b) -> a -> b
$ \Handle
h -> ExceptT FTCryptoError IO a -> IO (Either FTCryptoError a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT FTCryptoError IO a -> IO (Either FTCryptoError a))
-> ExceptT FTCryptoError IO a -> IO (Either FTCryptoError a)
forall a b. (a -> b) -> a -> b
$ CryptoFileHandle -> ExceptT FTCryptoError IO a
action (CryptoFileHandle -> ExceptT FTCryptoError IO a)
-> CryptoFileHandle -> ExceptT FTCryptoError IO a
forall a b. (a -> b) -> a -> b
$ Handle -> Maybe (TVar SbState) -> CryptoFileHandle
CFHandle Handle
h Maybe (TVar SbState)
sb
hPut :: CryptoFileHandle -> LazyByteString -> IO ()
hPut :: CryptoFileHandle -> LazyByteString -> IO ()
hPut (CFHandle Handle
h Maybe (TVar SbState)
sb_) LazyByteString
s = Handle -> LazyByteString -> IO ()
LB.hPut Handle
h (LazyByteString -> IO ()) -> IO LazyByteString -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO LazyByteString
-> (TVar SbState -> IO LazyByteString)
-> Maybe (TVar SbState)
-> IO LazyByteString
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (LazyByteString -> IO LazyByteString
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure LazyByteString
s) TVar SbState -> IO LazyByteString
forall {m :: * -> *}. MonadIO m => TVar SbState -> m LazyByteString
encrypt Maybe (TVar SbState)
sb_
where
encrypt :: TVar SbState -> m LazyByteString
encrypt TVar SbState
sb = STM LazyByteString -> m LazyByteString
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM LazyByteString -> m LazyByteString)
-> STM LazyByteString -> m LazyByteString
forall a b. (a -> b) -> a -> b
$ TVar SbState
-> (SbState -> (LazyByteString, SbState)) -> STM LazyByteString
forall s a. TVar s -> (s -> (a, s)) -> STM a
stateTVar TVar SbState
sb (SbState -> LazyByteString -> (LazyByteString, SbState)
`LC.sbEncryptChunkLazy` LazyByteString
s)
hPutTag :: CryptoFileHandle -> IO ()
hPutTag :: CryptoFileHandle -> IO ()
hPutTag (CFHandle Handle
h Maybe (TVar SbState)
sb_) = Maybe (TVar SbState) -> (TVar SbState -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (TVar SbState)
sb_ ((TVar SbState -> IO ()) -> IO ())
-> (TVar SbState -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ Handle -> ByteString -> IO ()
B.hPut Handle
h (ByteString -> IO ())
-> (SbState -> ByteString) -> SbState -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Auth -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
BA.convert (Auth -> ByteString) -> (SbState -> Auth) -> SbState -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SbState -> Auth
LC.sbAuth (SbState -> IO ())
-> (TVar SbState -> IO SbState) -> TVar SbState -> IO ()
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< TVar SbState -> IO SbState
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO
hGet :: CryptoFileHandle -> Int -> IO ByteString
hGet :: CryptoFileHandle -> Int -> IO ByteString
hGet (CFHandle Handle
h Maybe (TVar SbState)
sb_) Int
n = Handle -> Int -> IO ByteString
B.hGet Handle
h Int
n IO ByteString -> (ByteString -> IO ByteString) -> IO ByteString
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (ByteString -> IO ByteString)
-> (TVar SbState -> ByteString -> IO ByteString)
-> Maybe (TVar SbState)
-> ByteString
-> IO ByteString
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ByteString -> IO ByteString
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure TVar SbState -> ByteString -> IO ByteString
forall {m :: * -> *}.
MonadIO m =>
TVar SbState -> ByteString -> m ByteString
decrypt Maybe (TVar SbState)
sb_
where
decrypt :: TVar SbState -> ByteString -> m ByteString
decrypt TVar SbState
sb ByteString
s = STM ByteString -> m ByteString
forall (m :: * -> *) a. MonadIO m => STM a -> m a
atomically (STM ByteString -> m ByteString) -> STM ByteString -> m ByteString
forall a b. (a -> b) -> a -> b
$ TVar SbState
-> (SbState -> (ByteString, SbState)) -> STM ByteString
forall s a. TVar s -> (s -> (a, s)) -> STM a
stateTVar TVar SbState
sb (SbState -> ByteString -> (ByteString, SbState)
`LC.sbDecryptChunk` ByteString
s)
hGetTag :: CryptoFileHandle -> ExceptT FTCryptoError IO ()
hGetTag :: CryptoFileHandle -> ExceptT FTCryptoError IO ()
hGetTag (CFHandle Handle
h Maybe (TVar SbState)
sb_) = Maybe (TVar SbState)
-> (TVar SbState -> ExceptT FTCryptoError IO ())
-> ExceptT FTCryptoError IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (TVar SbState)
sb_ ((TVar SbState -> ExceptT FTCryptoError IO ())
-> ExceptT FTCryptoError IO ())
-> (TVar SbState -> ExceptT FTCryptoError IO ())
-> ExceptT FTCryptoError IO ()
forall a b. (a -> b) -> a -> b
$ \TVar SbState
sb -> do
ByteString
tag <- IO ByteString -> ExceptT FTCryptoError IO ByteString
forall a. IO a -> ExceptT FTCryptoError IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ByteString -> ExceptT FTCryptoError IO ByteString)
-> IO ByteString -> ExceptT FTCryptoError IO ByteString
forall a b. (a -> b) -> a -> b
$ Handle -> Int -> IO ByteString
B.hGet Handle
h Int
C.authTagSize
Auth
tag' <- SbState -> Auth
LC.sbAuth (SbState -> Auth)
-> ExceptT FTCryptoError IO SbState
-> ExceptT FTCryptoError IO Auth
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TVar SbState -> ExceptT FTCryptoError IO SbState
forall (m :: * -> *) a. MonadIO m => TVar a -> m a
readTVarIO TVar SbState
sb
Bool -> ExceptT FTCryptoError IO () -> ExceptT FTCryptoError IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> Auth -> Bool
forall bs1 bs2.
(ByteArrayAccess bs1, ByteArrayAccess bs2) =>
bs1 -> bs2 -> Bool
BA.constEq ByteString
tag Auth
tag') (ExceptT FTCryptoError IO () -> ExceptT FTCryptoError IO ())
-> ExceptT FTCryptoError IO () -> ExceptT FTCryptoError IO ()
forall a b. (a -> b) -> a -> b
$ FTCryptoError -> ExceptT FTCryptoError IO ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE FTCryptoError
FTCEInvalidAuthTag
data FTCryptoError
= FTCECryptoError C.CryptoError
| String
| FTCEInvalidFileSize
| FTCEInvalidAuthTag
| FTCEFileIOError String
deriving (Int -> FTCryptoError -> ShowS
[FTCryptoError] -> ShowS
FTCryptoError -> FilePath
(Int -> FTCryptoError -> ShowS)
-> (FTCryptoError -> FilePath)
-> ([FTCryptoError] -> ShowS)
-> Show FTCryptoError
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FTCryptoError -> ShowS
showsPrec :: Int -> FTCryptoError -> ShowS
$cshow :: FTCryptoError -> FilePath
show :: FTCryptoError -> FilePath
$cshowList :: [FTCryptoError] -> ShowS
showList :: [FTCryptoError] -> ShowS
Show, FTCryptoError -> FTCryptoError -> Bool
(FTCryptoError -> FTCryptoError -> Bool)
-> (FTCryptoError -> FTCryptoError -> Bool) -> Eq FTCryptoError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FTCryptoError -> FTCryptoError -> Bool
== :: FTCryptoError -> FTCryptoError -> Bool
$c/= :: FTCryptoError -> FTCryptoError -> Bool
/= :: FTCryptoError -> FTCryptoError -> Bool
Eq, Show FTCryptoError
Typeable FTCryptoError
(Typeable FTCryptoError, Show FTCryptoError) =>
(FTCryptoError -> SomeException)
-> (SomeException -> Maybe FTCryptoError)
-> (FTCryptoError -> FilePath)
-> Exception FTCryptoError
SomeException -> Maybe FTCryptoError
FTCryptoError -> FilePath
FTCryptoError -> SomeException
forall e.
(Typeable e, Show e) =>
(e -> SomeException)
-> (SomeException -> Maybe e) -> (e -> FilePath) -> Exception e
$ctoException :: FTCryptoError -> SomeException
toException :: FTCryptoError -> SomeException
$cfromException :: SomeException -> Maybe FTCryptoError
fromException :: SomeException -> Maybe FTCryptoError
$cdisplayException :: FTCryptoError -> FilePath
displayException :: FTCryptoError -> FilePath
Exception)
plain :: FilePath -> CryptoFile
plain :: FilePath -> CryptoFile
plain = (FilePath -> Maybe CryptoFileArgs -> CryptoFile
`CryptoFile` Maybe CryptoFileArgs
forall a. Maybe a
Nothing)
randomArgs :: TVar ChaChaDRG -> STM CryptoFileArgs
randomArgs :: TVar ChaChaDRG -> STM CryptoFileArgs
randomArgs TVar ChaChaDRG
g = SbKey -> CbNonce -> CryptoFileArgs
CFArgs (SbKey -> CbNonce -> CryptoFileArgs)
-> STM SbKey -> STM (CbNonce -> CryptoFileArgs)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TVar ChaChaDRG -> STM SbKey
C.randomSbKey TVar ChaChaDRG
g STM (CbNonce -> CryptoFileArgs)
-> STM CbNonce -> STM CryptoFileArgs
forall a b. STM (a -> b) -> STM a -> STM b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TVar ChaChaDRG -> STM CbNonce
C.randomCbNonce TVar ChaChaDRG
g
getFileContentsSize :: CryptoFile -> IO Integer
getFileContentsSize :: CryptoFile -> IO Integer
getFileContentsSize (CryptoFile FilePath
path Maybe CryptoFileArgs
cfArgs) = do
Integer
size <- FilePath -> IO Integer
getFileSize FilePath
path
Integer -> IO Integer
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Integer -> IO Integer) -> Integer -> IO Integer
forall a b. (a -> b) -> a -> b
$ if Maybe CryptoFileArgs -> Bool
forall a. Maybe a -> Bool
isJust Maybe CryptoFileArgs
cfArgs then Integer
size Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
C.authTagSize else Integer
size
$(J.deriveJSON defaultJSON ''CryptoFileArgs)
$(J.deriveJSON defaultJSON ''CryptoFile)