module Crypto.Noise.Internal.CipherState where
import Control.Exception.Safe
import Control.Lens
import Crypto.Noise.Cipher
import Crypto.Noise.Exception
data CipherState c =
CipherState { _csk :: Maybe (SymmetricKey c)
, _csn :: Nonce c
} deriving Show
$(makeLenses ''CipherState)
cipherState :: Cipher c
=> Maybe (SymmetricKey c)
-> CipherState c
cipherState sk = CipherState sk cipherZeroNonce
encryptWithAd :: (MonadThrow m, Cipher c)
=> AssocData
-> Plaintext
-> CipherState c
-> m (Ciphertext c, CipherState c)
encryptWithAd ad plaintext cs
| validNonce cs = return (result, newState)
| otherwise = throwM MessageLimitReached
where
result = maybe (cipherBytesToText plaintext)
(\k -> cipherEncrypt k (cs ^. csn) ad plaintext)
$ cs ^. csk
newState = cs & csn %~ cipherIncNonce
decryptWithAd :: (MonadThrow m, Cipher c)
=> AssocData
-> Ciphertext c
-> CipherState c
-> m (Plaintext, CipherState c)
decryptWithAd ad ct cs
| validNonce cs =
maybe (throwM DecryptionError)
(\x -> return (x, newState))
result
| otherwise = throwM MessageLimitReached
where
result = maybe (Just . cipherTextToBytes $ ct)
(\k -> cipherDecrypt k (cs ^. csn) ad ct)
$ cs ^. csk
newState = cs & csn %~ cipherIncNonce
rekey :: Cipher c
=> CipherState c
-> CipherState c
rekey cs = cs & csk %~ (<*>) (pure cipherRekey)
validNonce :: Cipher c
=> CipherState c
-> Bool
validNonce cs = cs ^. csn < cipherMaxNonce