{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeSynonymInstances #-}

module Crypto.HPKE.Types (
    HPKEError (..),
    Salt,
    IKM,
    Key,
    Suite,
    Label,
    KeyDeriveFunction,
    Nonce,
    AAD,
    PlainText,
    CipherText,
    Seal,
    Open,
    EncodedPublicKey (..),
    EncodedSecretKey (..),
    Info,
    PSK,
    PSK_ID,
    Encap,
    Decap,
    ExporterSecret,
    -- rexport
    CryptoFailable (..),
    SharedSecret (..),
    hashDigestSize,
    i2ospOf_,
    convert,
    Proxy (..),
    ByteString,
    Word8,
    Word16,
    printf,
    lookupE,
) where

import Control.Exception (Exception)
import Crypto.ECC (SharedSecret (..))
import Crypto.Error (CryptoFailable (..))
import Crypto.Hash.IO (hashDigestSize)
import Crypto.Number.Serialize (i2ospOf_)
import Data.ByteArray (convert)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Base16 as B16
import qualified Data.ByteString.Char8 as C8
import Data.Proxy (Proxy (..))
import Data.String
import Data.Word (Word16, Word8)
import Text.Printf (printf)

----------------------------------------------------------------

-- | Errors for HPKE
data HPKEError
    = ValidationError String
    | DeserializeError String
    | EncapError String
    | DecapError String
    | -- | Original
      SealError String
    | OpenError String
    | MessageLimitReachedError String
    | DeriveKeyPairError String
    | -- | Original
      KeyScheduleError String
    | Unsupported String
    deriving (HPKEError -> HPKEError -> Bool
(HPKEError -> HPKEError -> Bool)
-> (HPKEError -> HPKEError -> Bool) -> Eq HPKEError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: HPKEError -> HPKEError -> Bool
== :: HPKEError -> HPKEError -> Bool
$c/= :: HPKEError -> HPKEError -> Bool
/= :: HPKEError -> HPKEError -> Bool
Eq, Int -> HPKEError -> ShowS
[HPKEError] -> ShowS
HPKEError -> String
(Int -> HPKEError -> ShowS)
-> (HPKEError -> String)
-> ([HPKEError] -> ShowS)
-> Show HPKEError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> HPKEError -> ShowS
showsPrec :: Int -> HPKEError -> ShowS
$cshow :: HPKEError -> String
show :: HPKEError -> String
$cshowList :: [HPKEError] -> ShowS
showList :: [HPKEError] -> ShowS
Show)

instance Exception HPKEError

----------------------------------------------------------------

-- | Encryption key.
type Key = ByteString

type Salt = ByteString
type IKM = ByteString -- Input Keying Material
type Suite = ByteString
type Label = ByteString
type KeyDeriveFunction = SharedSecret -> ByteString -> Key

----------------------------------------------------------------

type Nonce = ByteString

-- | Additional authenticated data for AEAD.
type AAD = ByteString

-- | Plain text.
type PlainText = ByteString

-- | Cipher text (including a authentication tag)
type CipherText = ByteString

type Seal = Nonce -> AAD -> PlainText -> Either HPKEError CipherText
type Open = Nonce -> AAD -> CipherText -> Either HPKEError PlainText

----------------------------------------------------------------

-- | Encoded public key.
newtype EncodedPublicKey = EncodedPublicKey ByteString deriving (EncodedPublicKey -> EncodedPublicKey -> Bool
(EncodedPublicKey -> EncodedPublicKey -> Bool)
-> (EncodedPublicKey -> EncodedPublicKey -> Bool)
-> Eq EncodedPublicKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EncodedPublicKey -> EncodedPublicKey -> Bool
== :: EncodedPublicKey -> EncodedPublicKey -> Bool
$c/= :: EncodedPublicKey -> EncodedPublicKey -> Bool
/= :: EncodedPublicKey -> EncodedPublicKey -> Bool
Eq)

-- | Encoded secret key.
newtype EncodedSecretKey = EncodedSecretKey ByteString deriving (EncodedSecretKey -> EncodedSecretKey -> Bool
(EncodedSecretKey -> EncodedSecretKey -> Bool)
-> (EncodedSecretKey -> EncodedSecretKey -> Bool)
-> Eq EncodedSecretKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EncodedSecretKey -> EncodedSecretKey -> Bool
== :: EncodedSecretKey -> EncodedSecretKey -> Bool
$c/= :: EncodedSecretKey -> EncodedSecretKey -> Bool
/= :: EncodedSecretKey -> EncodedSecretKey -> Bool
Eq)

instance Show EncodedPublicKey where
    show :: EncodedPublicKey -> String
show (EncodedPublicKey ByteString
pk) = ByteString -> String
showBS16 ByteString
pk

instance Show EncodedSecretKey where
    show :: EncodedSecretKey -> String
show (EncodedSecretKey ByteString
pk) = ByteString -> String
showBS16 ByteString
pk

instance IsString EncodedPublicKey where
    fromString :: String -> EncodedPublicKey
fromString = ByteString -> EncodedPublicKey
EncodedPublicKey (ByteString -> EncodedPublicKey)
-> (String -> ByteString) -> String -> EncodedPublicKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
forall a. IsString a => String -> a
fromString

instance IsString EncodedSecretKey where
    fromString :: String -> EncodedSecretKey
fromString = ByteString -> EncodedSecretKey
EncodedSecretKey (ByteString -> EncodedSecretKey)
-> (String -> ByteString) -> String -> EncodedSecretKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
forall a. IsString a => String -> a
fromString

showBS16 :: ByteString -> String
showBS16 :: ByteString -> String
showBS16 ByteString
bs = String
"\"" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s16 String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"\""
  where
    s16 :: String
s16 = ByteString -> String
C8.unpack (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
B16.encode ByteString
bs

----------------------------------------------------------------

type Encap =
    EncodedPublicKey -> Either HPKEError (SharedSecret, EncodedPublicKey)
type Decap = EncodedPublicKey -> Either HPKEError SharedSecret

----------------------------------------------------------------

-- | Information string.
type Info = ByteString

-- | Pre-shared key.
type PSK = ByteString

-- | ID for pre-shared key.
type PSK_ID = ByteString

----------------------------------------------------------------

lookupE :: (Eq k, Show k) => k -> [(k, v)] -> Either HPKEError v
lookupE :: forall k v. (Eq k, Show k) => k -> [(k, v)] -> Either HPKEError v
lookupE k
k [(k, v)]
table = case k -> [(k, v)] -> Maybe v
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup k
k [(k, v)]
table of
    Maybe v
Nothing -> HPKEError -> Either HPKEError v
forall a b. a -> Either a b
Left (HPKEError -> Either HPKEError v)
-> HPKEError -> Either HPKEError v
forall a b. (a -> b) -> a -> b
$ String -> HPKEError
Unsupported (String -> HPKEError) -> String -> HPKEError
forall a b. (a -> b) -> a -> b
$ k -> String
forall a. Show a => a -> String
show k
k
    Just v
v -> v -> Either HPKEError v
forall a b. b -> Either a b
Right v
v

----------------------------------------------------------------

type ExporterSecret = ByteString