mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-03-30 14:16:00 +00:00
* agent: use large string encoding for contact link data * size-dependent user link data encoding * tag large user data encoding with \255
122 lines
5.3 KiB
Haskell
122 lines
5.3 KiB
Haskell
{-# LANGUAGE DataKinds #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
{-# LANGUAGE TypeApplications #-}
|
|
|
|
module AgentTests.ShortLinkTests (shortLinkTests) where
|
|
|
|
import AgentTests.ConnectionRequestTests (contactConnRequest, invConnRequest)
|
|
import AgentTests.EqInstances ()
|
|
import Control.Concurrent.STM
|
|
import Control.Monad.Except
|
|
import Simplex.Messaging.Agent.Protocol (AgentErrorType (..), ConnectionMode (..), LinkKey (..), SConnectionMode (..), SMPAgentError (..), UserLinkData (..), linkUserData, supportedSMPAgentVRange)
|
|
import qualified Simplex.Messaging.Crypto as C
|
|
import qualified Simplex.Messaging.Crypto.ShortLink as SL
|
|
import Test.Hspec hiding (fit, it)
|
|
import Util
|
|
|
|
shortLinkTests :: Spec
|
|
shortLinkTests = do
|
|
describe "invitation short link" $ do
|
|
it "should encrypt and decrypt link data" testInvShortLink
|
|
it "should fail to decrypt invitation data with bad hash" testInvShortLinkBadDataHash
|
|
describe "contact short link" $ do
|
|
it "should encrypt and decrypt data" testContactShortLink
|
|
it "should encrypt updated user data" testUpdateContactShortLink
|
|
it "should fail to decrypt contact data with bad hash" testContactShortLinkBadDataHash
|
|
it "should fail to decrypt contact data with bad signature" testContactShortLinkBadSignature
|
|
|
|
testInvShortLink :: IO ()
|
|
testInvShortLink = do
|
|
-- encrypt
|
|
g <- C.newRandom
|
|
sigKeys <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
|
let userData = UserLinkData "some user data"
|
|
(linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange invConnRequest userData
|
|
k = SL.invShortLinkKdf linkKey
|
|
Right srvData <- runExceptT $ SL.encryptLinkData g k linkData
|
|
-- decrypt
|
|
Right (connReq, connData') <- pure $ SL.decryptLinkData linkKey k srvData
|
|
connReq `shouldBe` invConnRequest
|
|
linkUserData connData' `shouldBe` userData
|
|
|
|
testInvShortLinkBadDataHash :: IO ()
|
|
testInvShortLinkBadDataHash = do
|
|
-- encrypt
|
|
g <- C.newRandom
|
|
sigKeys <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
|
let userData = UserLinkData "some user data"
|
|
(_linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange invConnRequest userData
|
|
-- different key
|
|
linkKey <- LinkKey <$> atomically (C.randomBytes 32 g)
|
|
let k = SL.invShortLinkKdf linkKey
|
|
Right srvData <- runExceptT $ SL.encryptLinkData g k linkData
|
|
-- decryption fails
|
|
SL.decryptLinkData @'CMInvitation linkKey k srvData
|
|
`shouldBe` Left (AGENT (A_LINK "link data hash"))
|
|
|
|
testContactShortLink :: IO ()
|
|
testContactShortLink = do
|
|
-- encrypt
|
|
g <- C.newRandom
|
|
sigKeys <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
|
let userData = UserLinkData "some user data"
|
|
(linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange contactConnRequest userData
|
|
(_linkId, k) = SL.contactShortLinkKdf linkKey
|
|
Right srvData <- runExceptT $ SL.encryptLinkData g k linkData
|
|
-- decrypt
|
|
Right (connReq, connData') <- pure $ SL.decryptLinkData linkKey k srvData
|
|
connReq `shouldBe` contactConnRequest
|
|
linkUserData connData' `shouldBe` userData
|
|
|
|
testUpdateContactShortLink :: IO ()
|
|
testUpdateContactShortLink = do
|
|
-- encrypt
|
|
g <- C.newRandom
|
|
sigKeys <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
|
let userData = UserLinkData "some user data"
|
|
(linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange contactConnRequest userData
|
|
(_linkId, k) = SL.contactShortLinkKdf linkKey
|
|
Right (fd, _ud) <- runExceptT $ SL.encryptLinkData g k linkData
|
|
-- encrypt updated user data
|
|
let updatedUserData = UserLinkData "updated user data"
|
|
signed = SL.encodeSignUserData SCMContact (snd sigKeys) supportedSMPAgentVRange updatedUserData
|
|
Right ud' <- runExceptT $ SL.encryptUserData g k signed
|
|
-- decrypt
|
|
Right (connReq, connData') <- pure $ SL.decryptLinkData linkKey k (fd, ud')
|
|
connReq `shouldBe` contactConnRequest
|
|
linkUserData connData' `shouldBe` updatedUserData
|
|
|
|
testContactShortLinkBadDataHash :: IO ()
|
|
testContactShortLinkBadDataHash = do
|
|
-- encrypt
|
|
g <- C.newRandom
|
|
sigKeys <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
|
let userData = UserLinkData "some user data"
|
|
(_linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange contactConnRequest userData
|
|
-- different key
|
|
linkKey <- LinkKey <$> atomically (C.randomBytes 32 g)
|
|
let (_linkId, k) = SL.contactShortLinkKdf linkKey
|
|
Right srvData <- runExceptT $ SL.encryptLinkData g k linkData
|
|
-- decryption fails
|
|
SL.decryptLinkData @'CMContact linkKey k srvData
|
|
`shouldBe` Left (AGENT (A_LINK "link data hash"))
|
|
|
|
testContactShortLinkBadSignature :: IO ()
|
|
testContactShortLinkBadSignature = do
|
|
-- encrypt
|
|
g <- C.newRandom
|
|
sigKeys <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
|
let userData = UserLinkData "some user data"
|
|
(linkKey, linkData) = SL.encodeSignLinkData sigKeys supportedSMPAgentVRange contactConnRequest userData
|
|
(_linkId, k) = SL.contactShortLinkKdf linkKey
|
|
Right (fd, _ud) <- runExceptT $ SL.encryptLinkData g k linkData
|
|
-- encrypt updated user data
|
|
let updatedUserData = UserLinkData "updated user data"
|
|
-- another signature key
|
|
(_, pk) <- atomically $ C.generateKeyPair @'C.Ed25519 g
|
|
let signed = SL.encodeSignUserData SCMContact pk supportedSMPAgentVRange updatedUserData
|
|
Right ud' <- runExceptT $ SL.encryptUserData g k signed
|
|
-- decryption fails
|
|
SL.decryptLinkData @'CMContact linkKey k (fd, ud')
|
|
`shouldBe` Left (AGENT (A_LINK "user data signature"))
|