packages feed

toxcore-0.2.11: test/Network/Tox/Crypto/KeyPairSpec.hs

{-# LANGUAGE Trustworthy #-}
module Network.Tox.Crypto.KeyPairSpec where

import           Control.Monad.IO.Class         (liftIO)
import qualified Crypto.Saltine.Class           as Sodium (encode)
import           Data.Proxy                     (Proxy (..))
import           Network.MessagePack.Rpc        (local)
import           Test.Hspec
import           Test.QuickCheck

import qualified Network.Tox.Crypto.Box         as Box
import qualified Network.Tox.Crypto.CombinedKey as CombinedKey
import qualified Network.Tox.Crypto.Key         as Key
import           Network.Tox.Crypto.KeyPair     (KeyPair (..))
import qualified Network.Tox.Crypto.KeyPair     as KeyPair
import           Network.Tox.EncodingSpec


spec :: Spec
spec = do
  rpcSpec (Proxy :: Proxy KeyPair)
  readShowSpec (Proxy :: Proxy KeyPair)

  describe "newKeyPair" $ do
    it "generates different key pairs on subsequent calls" $ do
      kp1 <- local KeyPair.newKeyPairR
      kp2 <- local KeyPair.newKeyPairR
      kp1 `shouldNotBe` kp2

    it "generates different secret keys on subsequent calls" $ do
      KeyPair sk1 _ <- local KeyPair.newKeyPairR
      KeyPair sk2 _ <- local KeyPair.newKeyPairR
      sk1 `shouldNotBe` sk2

    it "generates different public keys on subsequent calls" $ do
      KeyPair _ pk1 <- local KeyPair.newKeyPairR
      KeyPair _ pk2 <- local KeyPair.newKeyPairR
      pk1 `shouldNotBe` pk2

    it "generates a public key that is different from the secret key" $ do
      kp <- local KeyPair.newKeyPairR
      Sodium.encode (KeyPair.secretKey kp) `shouldNotBe` Sodium.encode (KeyPair.publicKey kp)

  describe "fromSecretKey" $ do
    it "doesn't modify the secret key" $
      property $ \sk -> do
        let KeyPair sk' _ = local KeyPair.fromSecretKeyR sk
        sk' `shouldBe` sk

    it "never computes a public key that is equal to the secret key" $
      property $ \sk -> do
        let KeyPair _ (Key.Key pk) = local KeyPair.fromSecretKeyR sk
        Sodium.encode pk `shouldNotBe` Sodium.encode sk

    it "computes a usable public key from an invalid secret key" $
      property $ \plainText nonce -> do
        let KeyPair sk pk = local KeyPair.fromSecretKeyR $ read "\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\""
        let ck = local CombinedKey.precomputeR sk pk
        let encrypted = local Box.encryptR ck nonce plainText
        let decrypted = local Box.decryptR ck nonce encrypted
        decrypted `shouldBe` Just plainText