module Signet.Unstable.Type.SignatureTest where

import qualified Control.Monad.Catch as Exception
import qualified Crypto.Error as Error
import qualified Crypto.Hash as Hash
import qualified Crypto.PubKey.Ed25519 as Ed25519
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Char8 as Ascii
import qualified Signet.Unstable.Exception.InvalidAsymmetricSignature as InvalidAsymmetricSignature
import qualified Signet.Unstable.Exception.InvalidSignature as InvalidSignature
import qualified Signet.Unstable.Exception.InvalidSymmetricSignature as InvalidSymmetricSignature
import qualified Signet.Unstable.Exception.UnknownSignature as UnknownSignature
import qualified Signet.Unstable.Extra.Either as Either
import qualified Signet.Unstable.Type.AsymmetricSignature as AsymmetricSignature
import qualified Signet.Unstable.Type.Signature as Signature
import qualified Signet.Unstable.Type.SymmetricSignature as SymmetricSignature
import qualified Signet.Unstable.Type.Test as Test

spec :: (Exception.MonadThrow io, Monad tree) => Test.Test io tree -> tree ()
spec :: forall (io :: * -> *) (tree :: * -> *).
(MonadThrow io, Monad tree) =>
Test io tree -> tree ()
spec Test io tree
test = Test io tree -> String -> tree () -> tree ()
forall (io :: * -> *) (tree :: * -> *).
Test io tree -> String -> tree () -> tree ()
Test.describe Test io tree
test String
"Signet.Unstable.Type.Signature" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
  Test io tree -> String -> tree () -> tree ()
forall (io :: * -> *) (tree :: * -> *).
Test io tree -> String -> tree () -> tree ()
Test.describe Test io tree
test String
"parse" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
    Test io tree -> String -> io () -> tree ()
forall (io :: * -> *) (tree :: * -> *).
Test io tree -> String -> io () -> tree ()
Test.it Test io tree
test String
"fails with invalid asymmetric signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let byteString :: ByteString
byteString = String -> ByteString
Ascii.pack String
"invalid"
      let result :: Either InvalidSignature (Either UnknownSignature Signature)
result = ByteString
-> Either InvalidSignature (Either UnknownSignature Signature)
Signature.parse (ByteString
 -> Either InvalidSignature (Either UnknownSignature Signature))
-> ByteString
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b. (a -> b) -> a -> b
$ String -> ByteString
Ascii.pack String
"v1a," ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
byteString
      Test io tree
-> Either InvalidSignature (Either UnknownSignature Signature)
-> Either InvalidSignature (Either UnknownSignature Signature)
-> io ()
forall (io :: * -> *) a (tree :: * -> *).
(HasCallStack, Applicative io, Eq a, Show a) =>
Test io tree -> a -> a -> io ()
Test.assertEq Test io tree
test Either InvalidSignature (Either UnknownSignature Signature)
result (InvalidSignature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b. a -> Either a b
Left (InvalidAsymmetricSignature -> InvalidSignature
InvalidSignature.InvalidAsymmetricSignature (InvalidAsymmetricSignature -> InvalidSignature)
-> InvalidAsymmetricSignature -> InvalidSignature
forall a b. (a -> b) -> a -> b
$ ByteString -> InvalidAsymmetricSignature
InvalidAsymmetricSignature.MkInvalidAsymmetricSignature ByteString
byteString))

    Test io tree -> String -> io () -> tree ()
forall (io :: * -> *) (tree :: * -> *).
Test io tree -> String -> io () -> tree ()
Test.it Test io tree
test String
"fails with invalid symmetric signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let byteString :: ByteString
byteString = String -> ByteString
Ascii.pack String
"invalid"
      let result :: Either InvalidSignature (Either UnknownSignature Signature)
result = ByteString
-> Either InvalidSignature (Either UnknownSignature Signature)
Signature.parse (ByteString
 -> Either InvalidSignature (Either UnknownSignature Signature))
-> ByteString
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b. (a -> b) -> a -> b
$ String -> ByteString
Ascii.pack String
"v1," ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
byteString
      Test io tree
-> Either InvalidSignature (Either UnknownSignature Signature)
-> Either InvalidSignature (Either UnknownSignature Signature)
-> io ()
forall (io :: * -> *) a (tree :: * -> *).
(HasCallStack, Applicative io, Eq a, Show a) =>
Test io tree -> a -> a -> io ()
Test.assertEq Test io tree
test Either InvalidSignature (Either UnknownSignature Signature)
result (InvalidSignature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b. a -> Either a b
Left (InvalidSymmetricSignature -> InvalidSignature
InvalidSignature.InvalidSymmetricSignature (InvalidSymmetricSignature -> InvalidSignature)
-> InvalidSymmetricSignature -> InvalidSignature
forall a b. (a -> b) -> a -> b
$ ByteString -> InvalidSymmetricSignature
InvalidSymmetricSignature.MkInvalidSymmetricSignature ByteString
byteString))

    Test io tree -> String -> io () -> tree ()
forall (io :: * -> *) (tree :: * -> *).
Test io tree -> String -> io () -> tree ()
Test.it Test io tree
test String
"returns unknown signature with unrecognized prefix" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let byteString :: ByteString
byteString = String -> ByteString
Ascii.pack String
"unknown"
      let result :: Either InvalidSignature (Either UnknownSignature Signature)
result = ByteString
-> Either InvalidSignature (Either UnknownSignature Signature)
Signature.parse ByteString
byteString
      Test io tree
-> Either InvalidSignature (Either UnknownSignature Signature)
-> Either InvalidSignature (Either UnknownSignature Signature)
-> io ()
forall (io :: * -> *) a (tree :: * -> *).
(HasCallStack, Applicative io, Eq a, Show a) =>
Test io tree -> a -> a -> io ()
Test.assertEq Test io tree
test Either InvalidSignature (Either UnknownSignature Signature)
result (Either UnknownSignature Signature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b. b -> Either a b
Right (UnknownSignature -> Either UnknownSignature Signature
forall a b. a -> Either a b
Left (UnknownSignature -> Either UnknownSignature Signature)
-> UnknownSignature -> Either UnknownSignature Signature
forall a b. (a -> b) -> a -> b
$ ByteString -> UnknownSignature
UnknownSignature.MkUnknownSignature ByteString
byteString))

    Test io tree -> String -> io () -> tree ()
forall (io :: * -> *) (tree :: * -> *).
Test io tree -> String -> io () -> tree ()
Test.it Test io tree
test String
"succeeds with valid asymmetric signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let byteString :: ByteString
byteString = String -> ByteString
Ascii.pack String
"v1a,QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVotMDEyMzQ1Njc4OS1hYmNkZWZnaGlqa2xtbm9wcXJzdHV2cXh5eg=="
      signature <- Either CryptoError Signature -> io Signature
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either CryptoError Signature -> io Signature)
-> (ByteString -> Either CryptoError Signature)
-> ByteString
-> io Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signature -> Signature)
-> Either CryptoError Signature -> Either CryptoError Signature
forall a b.
(a -> b) -> Either CryptoError a -> Either CryptoError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AsymmetricSignature -> Signature
Signature.Asymmetric (AsymmetricSignature -> Signature)
-> (Signature -> AsymmetricSignature) -> Signature -> Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signature -> AsymmetricSignature
AsymmetricSignature.MkAsymmetricSignature) (Either CryptoError Signature -> Either CryptoError Signature)
-> (ByteString -> Either CryptoError Signature)
-> ByteString
-> Either CryptoError Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CryptoFailable Signature -> Either CryptoError Signature
forall a. CryptoFailable a -> Either CryptoError a
Error.eitherCryptoError (CryptoFailable Signature -> Either CryptoError Signature)
-> (ByteString -> CryptoFailable Signature)
-> ByteString
-> Either CryptoError Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> CryptoFailable Signature
forall ba. ByteArrayAccess ba => ba -> CryptoFailable Signature
Ed25519.signature (ByteString -> io Signature) -> ByteString -> io Signature
forall a b. (a -> b) -> a -> b
$ String -> ByteString
Ascii.pack String
"ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789-abcdefghijklmnopqrstuvqxyz"
      Test.assertEq test (Signature.parse byteString) (Right (Right signature))

    Test io tree -> String -> io () -> tree ()
forall (io :: * -> *) (tree :: * -> *).
Test io tree -> String -> io () -> tree ()
Test.it Test io tree
test String
"succeeds with valid symmetric signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let byteString :: ByteString
byteString = String -> ByteString
Ascii.pack String
"v1,47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="
      let signature :: Signature
signature = SymmetricSignature -> Signature
Signature.Symmetric (SymmetricSignature -> Signature)
-> (Digest SHA256 -> SymmetricSignature)
-> Digest SHA256
-> Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digest SHA256 -> SymmetricSignature
SymmetricSignature.MkSymmetricSignature (Digest SHA256 -> Signature) -> Digest SHA256 -> Signature
forall a b. (a -> b) -> a -> b
$ ByteString -> Digest SHA256
forall ba a.
(ByteArrayAccess ba, HashAlgorithm a) =>
ba -> Digest a
Hash.hash ByteString
ByteString.empty
      Test io tree
-> Either InvalidSignature (Either UnknownSignature Signature)
-> Either InvalidSignature (Either UnknownSignature Signature)
-> io ()
forall (io :: * -> *) a (tree :: * -> *).
(HasCallStack, Applicative io, Eq a, Show a) =>
Test io tree -> a -> a -> io ()
Test.assertEq Test io tree
test (ByteString
-> Either InvalidSignature (Either UnknownSignature Signature)
Signature.parse ByteString
byteString) (Either UnknownSignature Signature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b. b -> Either a b
Right (Signature -> Either UnknownSignature Signature
forall a b. b -> Either a b
Right Signature
signature))

  Test io tree -> String -> tree () -> tree ()
forall (io :: * -> *) (tree :: * -> *).
Test io tree -> String -> tree () -> tree ()
Test.describe Test io tree
test String
"render" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
    Test io tree -> String -> io () -> tree ()
forall (io :: * -> *) (tree :: * -> *).
Test io tree -> String -> io () -> tree ()
Test.it Test io tree
test String
"renders asymmetric signature correctly" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      signature <- Either CryptoError Signature -> io Signature
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either CryptoError Signature -> io Signature)
-> (ByteString -> Either CryptoError Signature)
-> ByteString
-> io Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signature -> Signature)
-> Either CryptoError Signature -> Either CryptoError Signature
forall a b.
(a -> b) -> Either CryptoError a -> Either CryptoError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (AsymmetricSignature -> Signature
Signature.Asymmetric (AsymmetricSignature -> Signature)
-> (Signature -> AsymmetricSignature) -> Signature -> Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signature -> AsymmetricSignature
AsymmetricSignature.MkAsymmetricSignature) (Either CryptoError Signature -> Either CryptoError Signature)
-> (ByteString -> Either CryptoError Signature)
-> ByteString
-> Either CryptoError Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CryptoFailable Signature -> Either CryptoError Signature
forall a. CryptoFailable a -> Either CryptoError a
Error.eitherCryptoError (CryptoFailable Signature -> Either CryptoError Signature)
-> (ByteString -> CryptoFailable Signature)
-> ByteString
-> Either CryptoError Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> CryptoFailable Signature
forall ba. ByteArrayAccess ba => ba -> CryptoFailable Signature
Ed25519.signature (ByteString -> io Signature) -> ByteString -> io Signature
forall a b. (a -> b) -> a -> b
$ String -> ByteString
Ascii.pack String
"ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789-abcdefghijklmnopqrstuvqxyz"
      Test.assertEq test (Signature.render signature) (Ascii.pack "v1a,QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVotMDEyMzQ1Njc4OS1hYmNkZWZnaGlqa2xtbm9wcXJzdHV2cXh5eg==")

    Test io tree -> String -> io () -> tree ()
forall (io :: * -> *) (tree :: * -> *).
Test io tree -> String -> io () -> tree ()
Test.it Test io tree
test String
"renders symmetric signature correctly" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let signature :: Signature
signature = SymmetricSignature -> Signature
Signature.Symmetric (SymmetricSignature -> Signature)
-> (Digest SHA256 -> SymmetricSignature)
-> Digest SHA256
-> Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digest SHA256 -> SymmetricSignature
SymmetricSignature.MkSymmetricSignature (Digest SHA256 -> Signature) -> Digest SHA256 -> Signature
forall a b. (a -> b) -> a -> b
$ ByteString -> Digest SHA256
forall ba a.
(ByteArrayAccess ba, HashAlgorithm a) =>
ba -> Digest a
Hash.hash ByteString
ByteString.empty
      Test io tree -> ByteString -> ByteString -> io ()
forall (io :: * -> *) a (tree :: * -> *).
(HasCallStack, Applicative io, Eq a, Show a) =>
Test io tree -> a -> a -> io ()
Test.assertEq Test io tree
test (Signature -> ByteString
Signature.render Signature
signature) (String -> ByteString
Ascii.pack String
"v1,47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=")