module PipelineTests ( tests ) where import Protolude hiding (putByteString, Selector) import Test.Hspec import Conduit ((.|)) import qualified Crypto.Saltine.Class as Saltine import qualified Crypto.Saltine.Core.SecretBox as SecretBox import qualified Data.Conduit as C import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.Serialization.Binary as CSB import qualified Data.ByteString as BS import Data.Binary (Put) import Data.Binary.Put (putWord32be, putByteString) import Transit.Internal.Pipeline import Transit.Internal.Crypto (CryptoError) tests :: IO () tests = hspec $ do describe "assembleRecordC tests" $ do it "tests assembleRecordC with a short bytestring input" $ do let str = "hello" :: ByteString xs <- liftIO $ C.runConduitRes $ CSB.sourcePut (putChunk str) .| assembleRecordC .| CB.isolate (BS.length str) .| CB.sinkLbs xs `shouldBe` (toS str) describe "decryptC tests" $ do it "tests a encryptC/decryptC round trip" $ do let key = fromMaybe (panic "cannot decode key") $ Saltine.decode ("0123456789abcdef0123456789abcdef" :: ByteString) plaintext = "foobar" :: ByteString xs <- liftIO (C.runConduitRes $ CSB.sourcePut (putByteString plaintext) .| encryptC key .| assembleRecordC .| decryptC key .| CB.isolate (BS.length plaintext) .| CB.sinkLbs) xs `shouldBe` (toS plaintext) it "throws CryptoError when a wrong nonce is encountered" $ do -- create a packet with a non-zero nonce concatenated with -- random input. Feed it as a source into decryptC and feed -- output into a sinkLbs. This should throw a BadNonce -- exception, as decryptC expects a nonce/sequence number of 0. let nonce = Saltine.nudge Saltine.zero :: SecretBox.Nonce key = fromMaybe (panic "cannot decode key") $ Saltine.decode ("0123456789abcdef0123456789abcdef" :: ByteString) nonceBytes = Saltine.encode nonce plaintext = "foobar" :: ByteString packet = nonceBytes <> plaintext liftIO (C.runConduitRes $ CSB.sourcePut (putByteString packet) .| decryptC key .| CB.isolate (BS.length packet) .| CB.sinkLbs) `shouldThrow` cryptoError where putChunk :: ByteString -> Put putChunk s = do let strlen = BS.length s putWord32be (fromIntegral @Int strlen) putByteString s cryptoError :: Selector CryptoError cryptoError = const True