module Test.MLS.Keys where

import API.Galley
import qualified Data.ByteString.Base64 as B64
import qualified Data.ByteString.Base64.URL as B64U
import qualified Data.ByteString.Char8 as B8
import SetupHelpers
import Testlib.Prelude

testRawPublicKeys :: (HasCallStack) => App ()
testRawPublicKeys :: HasCallStack => App ()
testRawPublicKeys = do
  Value
u <- Domain -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> App Value
randomUserId Domain
OwnDomain
  Value
keys <- Value -> App Response
forall user.
(HasCallStack, MakesValue user) =>
user -> App Response
getMLSPublicKeys Value
u App Response -> (Response -> App Value) -> App Value
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= HasCallStack => Int -> Response -> App Value
Int -> Response -> App Value
getJSON Int
200

  do
    String
pubkeyS <- Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ed25519" App Value -> (App Value -> App String) -> App String
forall a b. a -> (a -> b) -> b
& App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString
    ByteString
pubkey <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64.decode (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyS
    ByteString -> Int
B8.length ByteString
pubkey Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
32

  do
    String
pubkeyS <- Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp256r1_sha256" App Value -> (App Value -> App String) -> App String
forall a b. a -> (a -> b) -> b
& App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString
    ByteString
pubkey <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64.decode (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyS
    ByteString -> Int
B8.length ByteString
pubkey Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
65

  do
    String
pubkeyS <- Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp384r1_sha384" App Value -> (App Value -> App String) -> App String
forall a b. a -> (a -> b) -> b
& App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString
    ByteString
pubkey <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64.decode (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyS
    ByteString -> Int
B8.length ByteString
pubkey Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
97

  do
    String
pubkeyS <- Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp521r1_sha512" App Value -> (App Value -> App String) -> App String
forall a b. a -> (a -> b) -> b
& App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString
    ByteString
pubkey <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64.decode (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyS
    ByteString -> Int
B8.length ByteString
pubkey Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
133

testJWKPublicKeys :: (HasCallStack) => App ()
testJWKPublicKeys :: HasCallStack => App ()
testJWKPublicKeys = do
  Value
u <- Domain -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> App Value
randomUserId Domain
OwnDomain
  Value
keys <- Value -> App Response
forall user.
(HasCallStack, MakesValue user) =>
user -> App Response
getMLSPublicKeysJWK Value
u App Response -> (Response -> App Value) -> App Value
forall a b. App a -> (a -> App b) -> App b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= HasCallStack => Int -> Response -> App Value
Int -> Response -> App Value
getJSON Int
200

  do
    Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ed25519.crv" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
"Ed25519"
    Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ed25519.kty" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
"OKP"
    String
pubkeyS <- App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString (App Value -> App String) -> App Value -> App String
forall a b. (a -> b) -> a -> b
$ Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ed25519.x"
    ByteString
pubkey <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64U.decodeUnpadded (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyS
    ByteString -> Int
B8.length ByteString
pubkey Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
32

  do
    Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp256r1_sha256.crv" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
"P-256"
    Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp256r1_sha256.kty" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
"EC"
    String
pubkeyXS <- App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString (App Value -> App String) -> App Value -> App String
forall a b. (a -> b) -> a -> b
$ Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp256r1_sha256.x"
    ByteString
pubkeyX <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64U.decodeUnpadded (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyXS
    ByteString -> Int
B8.length ByteString
pubkeyX Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
32
    String
pubkeyYS <- App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString (App Value -> App String) -> App Value -> App String
forall a b. (a -> b) -> a -> b
$ Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp256r1_sha256.y"
    ByteString
pubkeyY <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64U.decodeUnpadded (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyYS
    ByteString -> Int
B8.length ByteString
pubkeyY Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
32

  do
    Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp384r1_sha384.crv" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
"P-384"
    Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp384r1_sha384.kty" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
"EC"
    String
pubkeyXS <- App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString (App Value -> App String) -> App Value -> App String
forall a b. (a -> b) -> a -> b
$ Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp384r1_sha384.x"
    ByteString
pubkeyX <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64U.decodeUnpadded (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyXS
    ByteString -> Int
B8.length ByteString
pubkeyX Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
48
    String
pubkeyYS <- App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString (App Value -> App String) -> App Value -> App String
forall a b. (a -> b) -> a -> b
$ Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp384r1_sha384.y"
    ByteString
pubkeyY <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64U.decodeUnpadded (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyYS
    ByteString -> Int
B8.length ByteString
pubkeyY Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
48

  do
    Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp521r1_sha512.crv" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
"P-521"
    Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp521r1_sha512.kty" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
"EC"
    String
pubkeyXS <- App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString (App Value -> App String) -> App Value -> App String
forall a b. (a -> b) -> a -> b
$ Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp521r1_sha512.x"
    ByteString
pubkeyX <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64U.decodeUnpadded (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyXS
    ByteString -> Int
B8.length ByteString
pubkeyX Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
66
    String
pubkeyYS <- App Value -> App String
forall a. (HasCallStack, MakesValue a) => a -> App String
asString (App Value -> App String) -> App Value -> App String
forall a b. (a -> b) -> a -> b
$ Value
keys Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"removal.ecdsa_secp521r1_sha512.y"
    ByteString
pubkeyY <- [ByteString] -> App ByteString
forall (t :: * -> *) a. (HasCallStack, Foldable t) => t a -> App a
assertOne ([ByteString] -> App ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> App ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either String ByteString -> [ByteString]
forall a. Either String a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Either String ByteString -> [ByteString])
-> (ByteString -> Either String ByteString)
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
B64U.decodeUnpadded (ByteString -> App ByteString) -> ByteString -> App ByteString
forall a b. (a -> b) -> a -> b
$ String -> ByteString
B8.pack String
pubkeyYS
    ByteString -> Int
B8.length ByteString
pubkeyY Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
66

testPublicKeysMLSNotEnabled :: (HasCallStack) => App ()
testPublicKeysMLSNotEnabled :: HasCallStack => App ()
testPublicKeysMLSNotEnabled = ServiceOverrides -> (HasCallStack => String -> App ()) -> App ()
forall a.
HasCallStack =>
ServiceOverrides -> (HasCallStack => String -> App a) -> App a
withModifiedBackend
  ServiceOverrides
forall a. Default a => a
def
    { galleyCfg = removeField "settings.mlsPrivateKeyPaths"
    }
  ((HasCallStack => String -> App ()) -> App ())
-> (HasCallStack => String -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \String
domain -> do
    Value
alice <- String -> App Value
forall domain.
(HasCallStack, MakesValue domain) =>
domain -> App Value
randomUserId String
domain
    App Response -> (Response -> App ()) -> App ()
forall a.
HasCallStack =>
App Response -> (Response -> App a) -> App a
bindResponse (Value -> App Response
forall user.
(HasCallStack, MakesValue user) =>
user -> App Response
getMLSPublicKeys Value
alice) ((Response -> App ()) -> App ()) -> (Response -> App ()) -> App ()
forall a b. (a -> b) -> a -> b
$ \Response
resp -> do
      Response
resp.status Int -> Int -> App ()
forall a. (MakesValue a, HasCallStack) => a -> Int -> App ()
`shouldMatchInt` Int
400
      Response
resp.json App Value -> String -> App Value
forall a. (HasCallStack, MakesValue a) => a -> String -> App Value
%. String
"label" App Value -> String -> App ()
forall a b.
(MakesValue a, MakesValue b, HasCallStack) =>
a -> b -> App ()
`shouldMatch` String
"mls-not-enabled"