jose-jwt-0.9.2: tests/Tests/JwkSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Tests.JwkSpec where
import Test.Hspec
import Test.HUnit hiding (Test)
import Data.Aeson
import qualified Data.ByteString.Char8 as B
import qualified Data.HashMap.Strict as H
import Data.Word (Word64)
import qualified Data.Vector as V
import Crypto.PubKey.ECC.ECDSA
import Crypto.PubKey.ECC.Types
import Crypto.Random (drgNewTest, withDRG)
import Jose.Jwt (defJwsHdr, JwsHeader(..), KeyId(..))
import Jose.Jwk
import Jose.Jwa
spec :: Spec
spec = do
jwkFile <- runIO (B.readFile "tests/jwks.json")
let Just (Object keySet) = decodeStrict jwkFile
Success s = fromJSON (Object keySet) :: Result JwkSet
Just s' = decode (encode s)
Just s'' = decode' (encode s')
kss = keys s'
k0 = head kss
k1 = kss !! 1
k3 = kss !! 3
k4 = kss !! 4
describe "JWK encoding and decoding" $ do
it "decodes and encodes an entire key set successfully" $ do
let RsaPublicJwk _ key0Id key0Use a0 = k0
RsaPublicJwk _ key1Id key1Use _ = k1
EcPublicJwk k key2Id key2Use _ _ = kss !! 2
EcPublicJwk _ key3Id key3Use _ _ = k3
SymmetricJwk _ key4Id Nothing _ = k4
EcPublicJwk _ key5Id (Just Enc) _ _ = kss !! 5
RsaPublicJwk _ key6Id Nothing a6 = kss !! 6
EcPrivateJwk _ key7Id (Just Enc) _ _ = kss !! 7
RsaPrivateJwk _ _ Nothing a8 = kss !! 8
Ed25519PrivateJwk _ _ key9Id = kss !! 9
Ed25519PublicJwk _ key10Id = kss !! 10
Success utcKeyId = fromJSON (String "2015-05-16T18:00:14.259Z")
length kss @?= 14
a0 @?= Nothing
key0Id @?= Just (KeyId "a0")
key1Id @?= Just (KeyId "a1")
key2Id @?= Just (KeyId "a2")
public_curve k @?= getCurveByName SEC_p256r1
key3Id @?= Just (KeyId "a3")
key4Id @?= Just (KeyId "HMAC key used in JWS A.1 example")
key5Id @?= Just (KeyId "1")
key6Id @?= Just (UTCKeyId utcKeyId)
key7Id @?= Just (KeyId "1")
key9Id @?= Just (KeyId "rfc8037SecretKey")
key10Id @?= Just (KeyId "rfc8037PublicKey")
key0Use @?= Just Enc
key1Use @?= Just Sig
key2Use @?= Just Sig
key3Use @?= Just Enc
a6 @?= Just (Signed RS256)
a8 @?= Just (Signed RS256)
isPublic k3 @?= True
isPublic k4 @?= False
isPrivate k4 @?= False
it "shameless Show and Eq coverage boosting" $ do
s' @?= s''
assertBool "Different sets aren't equal" (s' /= JwkSet { keys = take 8 kss ++ [k0]})
assertBool "Show stuff" $ showCov s' && showCov k0 && showCov k3 && showCov Sig
assertBool "Different keys should be unequal" (k0 /= k1)
describe "Errors in JWK data" $ do
let Just (Array ks) = H.lookup "keys" keySet
Object k0obj = V.head ks
it "invalid Base64 returns an error" $ do
let result = fromJSON (Object $ H.insert "n" (String "NotBase64**") k0obj) :: Result Jwk
case result of
Error _ -> assertBool "" True
_ -> assertFailure "Expected an error for invalid base 64"
describe "JWK Algorithm matching" $ do
let jwks = keys s
it "finds one key for RS256 encoding" $ do
-- Only the RSA Private key
let jwks' = filter (canEncodeJws RS256) jwks
length jwks' @?= 1
it "finds 3 keys for RS256 decoding with no kid" $ do
-- All RSA keys are valid except for the "enc" one
let jwks' = filter (canDecodeJws (defJwsHdr {jwsAlg = RS256})) jwks
length jwks' @?= 3
it "finds one key for RS256 decoding with kid specified" $ do
let jwks' = filter (canDecodeJws (defJwsHdr {jwsAlg = RS256, jwsKid = Just (KeyId "a1")})) jwks
length jwks' @?= 1
it "finds an RS1_5 key for encoding" $ do
-- Only key a0 matches. The other 3 RSA keys are signing keys
let jwks' = filter (canEncodeJwe RSA1_5) jwks
length jwks' @?= 1
describe "RSA Key generation" $ do
let rng = drgNewTest (w, w, w, w, w) where w = 1 :: Word64
kid = KeyId "mykey"
((kPub, kPr), _) = withDRG rng (generateRsaKeyPair 512 kid Sig Nothing)
it "keys generated with same RNG are equal" $ do
let ((kPub', kPr'), _) = withDRG rng (generateRsaKeyPair 512 kid Sig Nothing)
kPub' @?= kPub
kPr' @?= kPr
it "isPublic and isPrivate are correct for RSA keys" $ do
isPublic kPub @?= True
isPublic kPr @?= False
isPrivate kPr @?= True
it "keys have supplied ID" $ do
jwkId kPr @?= Just kid
jwkId kPub @?= Just kid
it "keys have supplied use" $ do
jwkUse kPr @?= Just Sig
jwkUse kPub @?= Just Sig
where
showCov x = showList [x] `seq` showsPrec 1 x `seq` show x `seq` True