{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {- HLINT ignore "Reduce duplication" -} module Spec.Crypto (specs) where import Data.ByteString (ByteString) import Data.List.NonEmpty (NonEmpty ((:|))) import Test.Tasty import Test.Tasty.HUnit import Auth.Biscuit import qualified Auth.Biscuit.Sel as Sel import Auth.Biscuit.Token (Biscuit (..)) specs :: TestTree specs = testGroup "biscuit crypto" [ testGroup "signature algorithm" [ singleBlockRoundtrip , multiBlockRoundtrip , tamperedAuthority , tamperedBlock ] , testGroup "high-level functions" [ singleBlockRoundtrip' , multiBlockRoundtrip' , tamperedAuthority' , tamperedBlock' ] ] singleBlockRoundtrip :: TestTree singleBlockRoundtrip = testCase "Single block roundtrip" $ do rootKp <- newKeypair let pub = publicKey rootKp content = "content" token = (pub, content) :| [] sig <- Sel.signBlock rootKp content result <- Sel.verifySignature token sig result @?= True multiBlockRoundtrip :: TestTree multiBlockRoundtrip = testCase "Multi block roundtrip" $ do kp' <- newKeypair kp <- newKeypair let pub = publicKey kp pub' = publicKey kp' content = "content" content' = "block" token = (pub, content) :| [(pub', content')] sig <- Sel.signBlock kp content sig' <- Sel.aggregate sig =<< Sel.signBlock kp' content' result <- Sel.verifySignature token sig' result @?= True tamperedAuthority :: TestTree tamperedAuthority = testCase "Tampered authority" $ do kp' <- newKeypair kp <- newKeypair let pub = publicKey kp pub' = publicKey kp' content = "content" content' = "block" token = (pub, "modified") :| [] token' = (pub, "modified") :| [(pub', content')] sig <- Sel.signBlock kp content sig' <- Sel.aggregate sig =<< Sel.signBlock kp' content' result <- Sel.verifySignature token sig' result @?= False result' <- Sel.verifySignature token' sig' result' @?= False tamperedBlock :: TestTree tamperedBlock = testCase "Tampered block" $ do kp' <- newKeypair kp <- newKeypair let pub = publicKey kp pub' = publicKey kp' content = "content" content' = "block" token = (pub, content) :| [(pub', "modified")] sig <- Sel.signBlock kp content sig' <- Sel.aggregate sig =<< Sel.signBlock kp' content' result <- Sel.verifySignature token sig' result @?= False singleBlockRoundtrip' :: TestTree singleBlockRoundtrip' = testCase "Single block roundtrip" $ do rootKp <- newKeypair let pub = publicKey rootKp b <- mkBiscuit rootKp [block|right(#authority,#read);|] result <- checkBiscuitSignature b pub result @?= True multiBlockRoundtrip' :: TestTree multiBlockRoundtrip' = testCase "Multi block roundtrip" $ do kp <- newKeypair let pub = publicKey kp b <- mkBiscuit kp [block|right(#authority,#read);|] b' <- addBlock [block|check if true;|] b result <- checkBiscuitSignature b' pub result @?= True tamper :: (PublicKey, (ByteString, Block)) -> (PublicKey, (ByteString, Block)) tamper (pk, (_, b)) = (pk, ("tampered", b)) tamperedAuthority' :: TestTree tamperedAuthority' = testCase "Tampered authority" $ do kp <- newKeypair let pub = publicKey kp b <- mkBiscuit kp [block|right(#authority,#read);|] b' <- addBlock [block|check if true;|] b let modified = b' { authority = tamper $ authority b } result <- checkBiscuitSignature modified pub result @?= False tamperedBlock' :: TestTree tamperedBlock' = testCase "Tampered block" $ do kp <- newKeypair let pub = publicKey kp b <- mkBiscuit kp [block|right(#authority,#read);|] b' <- addBlock [block|check if true;|] b let modified = b' { blocks = tamper <$> blocks b } result <- checkBiscuitSignature modified pub result @?= False