module Signet.Unstable.Type.Verifier where

import qualified Crypto.PubKey.Ed25519 as Ed25519
import qualified Data.ByteString as ByteString
import qualified Data.List as List
import qualified Data.Maybe as Maybe
import qualified Signet.Unstable.Exception.InvalidVerifier as InvalidVerifier
import qualified Signet.Unstable.Exception.VerificationException as VerificationException
import qualified Signet.Unstable.Extra.Maybe as Maybe
import qualified Signet.Unstable.Type.AsymmetricSignature as AsymmetricSignature
import qualified Signet.Unstable.Type.Message as Message
import qualified Signet.Unstable.Type.PublicKey as PublicKey
import qualified Signet.Unstable.Type.Secret as Secret
import qualified Signet.Unstable.Type.Signature as Signature
import qualified Signet.Unstable.Type.Signatures as Signatures
import qualified Signet.Unstable.Type.Signer as Signer
import qualified Signet.Unstable.Type.SymmetricSignature as SymmetricSignature

data Verifier
  = Asymmetric PublicKey.PublicKey
  | Symmetric Secret.Secret
  deriving (Verifier -> Verifier -> Bool
(Verifier -> Verifier -> Bool)
-> (Verifier -> Verifier -> Bool) -> Eq Verifier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Verifier -> Verifier -> Bool
== :: Verifier -> Verifier -> Bool
$c/= :: Verifier -> Verifier -> Bool
/= :: Verifier -> Verifier -> Bool
Eq, Int -> Verifier -> ShowS
[Verifier] -> ShowS
Verifier -> String
(Int -> Verifier -> ShowS)
-> (Verifier -> String) -> ([Verifier] -> ShowS) -> Show Verifier
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Verifier -> ShowS
showsPrec :: Int -> Verifier -> ShowS
$cshow :: Verifier -> String
show :: Verifier -> String
$cshowList :: [Verifier] -> ShowS
showList :: [Verifier] -> ShowS
Show)

parse :: ByteString.ByteString -> Either InvalidVerifier.InvalidVerifier Verifier
parse :: ByteString -> Either InvalidVerifier Verifier
parse ByteString
byteString = case ByteString -> Either InvalidPublicKey PublicKey
PublicKey.parse ByteString
byteString of
  Right PublicKey
publicKey -> Verifier -> Either InvalidVerifier Verifier
forall a b. b -> Either a b
Right (Verifier -> Either InvalidVerifier Verifier)
-> Verifier -> Either InvalidVerifier Verifier
forall a b. (a -> b) -> a -> b
$ PublicKey -> Verifier
Asymmetric PublicKey
publicKey
  Left InvalidPublicKey
_ -> case ByteString -> Either InvalidSecret Secret
Secret.parse ByteString
byteString of
    Right Secret
secret -> Verifier -> Either InvalidVerifier Verifier
forall a b. b -> Either a b
Right (Verifier -> Either InvalidVerifier Verifier)
-> Verifier -> Either InvalidVerifier Verifier
forall a b. (a -> b) -> a -> b
$ Secret -> Verifier
Symmetric Secret
secret
    Left InvalidSecret
_ -> InvalidVerifier -> Either InvalidVerifier Verifier
forall a b. a -> Either a b
Left (InvalidVerifier -> Either InvalidVerifier Verifier)
-> InvalidVerifier -> Either InvalidVerifier Verifier
forall a b. (a -> b) -> a -> b
$ ByteString -> InvalidVerifier
InvalidVerifier.MkInvalidVerifier ByteString
byteString

render :: Verifier -> ByteString.ByteString
render :: Verifier -> ByteString
render Verifier
verifier = case Verifier
verifier of
  Asymmetric PublicKey
publicKey -> PublicKey -> ByteString
PublicKey.render PublicKey
publicKey
  Symmetric Secret
secret -> Secret -> ByteString
Secret.render Secret
secret

verify ::
  Verifier ->
  Message.Message ->
  Signatures.Signatures ->
  Either VerificationException.VerificationException Signature.Signature
verify :: Verifier
-> Message -> Signatures -> Either VerificationException Signature
verify Verifier
verifier Message
message =
  case Verifier
verifier of
    Asymmetric PublicKey
publicKey -> (AsymmetricSignature -> Signature)
-> Either VerificationException AsymmetricSignature
-> Either VerificationException Signature
forall a b.
(a -> b)
-> Either VerificationException a -> Either VerificationException b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap AsymmetricSignature -> Signature
Signature.Asymmetric (Either VerificationException AsymmetricSignature
 -> Either VerificationException Signature)
-> (Signatures -> Either VerificationException AsymmetricSignature)
-> Signatures
-> Either VerificationException Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PublicKey
-> Message
-> Signatures
-> Either VerificationException AsymmetricSignature
asymmetric PublicKey
publicKey Message
message
    Symmetric Secret
secret -> (SymmetricSignature -> Signature)
-> Either VerificationException SymmetricSignature
-> Either VerificationException Signature
forall a b.
(a -> b)
-> Either VerificationException a -> Either VerificationException b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SymmetricSignature -> Signature
Signature.Symmetric (Either VerificationException SymmetricSignature
 -> Either VerificationException Signature)
-> (Signatures -> Either VerificationException SymmetricSignature)
-> Signatures
-> Either VerificationException Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Secret
-> Message
-> Signatures
-> Either VerificationException SymmetricSignature
symmetric Secret
secret Message
message

asymmetric ::
  PublicKey.PublicKey ->
  Message.Message ->
  Signatures.Signatures ->
  Either VerificationException.VerificationException AsymmetricSignature.AsymmetricSignature
asymmetric :: PublicKey
-> Message
-> Signatures
-> Either VerificationException AsymmetricSignature
asymmetric PublicKey
publicKey Message
message =
  let toAsymmetric :: Signature -> Maybe AsymmetricSignature
toAsymmetric Signature
signature = case Signature
signature of
        Signature.Asymmetric AsymmetricSignature
asymmetricSignature -> AsymmetricSignature -> Maybe AsymmetricSignature
forall a. a -> Maybe a
Just AsymmetricSignature
asymmetricSignature
        Signature.Symmetric SymmetricSignature
_ -> Maybe AsymmetricSignature
forall a. Maybe a
Nothing
      pk :: PublicKey
pk = PublicKey -> PublicKey
PublicKey.unwrap PublicKey
publicKey
      bs :: ByteString
bs = Message -> ByteString
Message.render Message
message
   in VerificationException
-> Maybe AsymmetricSignature
-> Either VerificationException AsymmetricSignature
forall e a. e -> Maybe a -> Either e a
Maybe.note (Id -> VerificationException
VerificationException.MkVerificationException (Id -> VerificationException) -> Id -> VerificationException
forall a b. (a -> b) -> a -> b
$ Message -> Id
Message.id_ Message
message)
        (Maybe AsymmetricSignature
 -> Either VerificationException AsymmetricSignature)
-> (Signatures -> Maybe AsymmetricSignature)
-> Signatures
-> Either VerificationException AsymmetricSignature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AsymmetricSignature -> Bool)
-> [AsymmetricSignature] -> Maybe AsymmetricSignature
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
List.find (PublicKey -> ByteString -> Signature -> Bool
forall ba.
ByteArrayAccess ba =>
PublicKey -> ba -> Signature -> Bool
Ed25519.verify PublicKey
pk ByteString
bs (Signature -> Bool)
-> (AsymmetricSignature -> Signature)
-> AsymmetricSignature
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AsymmetricSignature -> Signature
AsymmetricSignature.unwrap)
        ([AsymmetricSignature] -> Maybe AsymmetricSignature)
-> (Signatures -> [AsymmetricSignature])
-> Signatures
-> Maybe AsymmetricSignature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signature -> Maybe AsymmetricSignature)
-> [Signature] -> [AsymmetricSignature]
forall a b. (a -> Maybe b) -> [a] -> [b]
Maybe.mapMaybe Signature -> Maybe AsymmetricSignature
toAsymmetric
        ([Signature] -> [AsymmetricSignature])
-> (Signatures -> [Signature])
-> Signatures
-> [AsymmetricSignature]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signatures -> [Signature]
Signatures.unwrap

symmetric ::
  Secret.Secret ->
  Message.Message ->
  Signatures.Signatures ->
  Either VerificationException.VerificationException SymmetricSignature.SymmetricSignature
symmetric :: Secret
-> Message
-> Signatures
-> Either VerificationException SymmetricSignature
symmetric Secret
secret Message
message =
  let toSymmetric :: Signature -> Maybe SymmetricSignature
toSymmetric Signature
signature = case Signature
signature of
        Signature.Asymmetric AsymmetricSignature
_ -> Maybe SymmetricSignature
forall a. Maybe a
Nothing
        Signature.Symmetric SymmetricSignature
symmetricSignature -> SymmetricSignature -> Maybe SymmetricSignature
forall a. a -> Maybe a
Just SymmetricSignature
symmetricSignature
      expected :: SymmetricSignature
expected = Secret -> Message -> SymmetricSignature
Signer.symmetric Secret
secret Message
message
   in VerificationException
-> Maybe SymmetricSignature
-> Either VerificationException SymmetricSignature
forall e a. e -> Maybe a -> Either e a
Maybe.note (Id -> VerificationException
VerificationException.MkVerificationException (Id -> VerificationException) -> Id -> VerificationException
forall a b. (a -> b) -> a -> b
$ Message -> Id
Message.id_ Message
message)
        (Maybe SymmetricSignature
 -> Either VerificationException SymmetricSignature)
-> (Signatures -> Maybe SymmetricSignature)
-> Signatures
-> Either VerificationException SymmetricSignature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SymmetricSignature -> Bool)
-> [SymmetricSignature] -> Maybe SymmetricSignature
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
List.find (SymmetricSignature
expected SymmetricSignature -> SymmetricSignature -> Bool
forall a. Eq a => a -> a -> Bool
==)
        ([SymmetricSignature] -> Maybe SymmetricSignature)
-> (Signatures -> [SymmetricSignature])
-> Signatures
-> Maybe SymmetricSignature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signature -> Maybe SymmetricSignature)
-> [Signature] -> [SymmetricSignature]
forall a b. (a -> Maybe b) -> [a] -> [b]
Maybe.mapMaybe Signature -> Maybe SymmetricSignature
toSymmetric
        ([Signature] -> [SymmetricSignature])
-> (Signatures -> [Signature])
-> Signatures
-> [SymmetricSignature]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signatures -> [Signature]
Signatures.unwrap