jose-0.4.0.0: test/Properties.hs
-- Copyright (C) 2015 Fraser Tweedale
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
{-# LANGUAGE ScopedTypeVariables #-}
module Properties where
import Control.Applicative
import Data.Aeson
import qualified Data.ByteString as B
import Data.Default.Class
import Test.Tasty
import Test.Tasty.QuickCheck
import Test.QuickCheck.Monadic
import Test.QuickCheck.Instances ()
import Crypto.JOSE.Types
import Crypto.JOSE.JWK
import Crypto.JOSE.JWS
properties = testGroup "Properties"
[ testProperty "SizedBase64Integer round-trip"
(prop_roundTrip :: SizedBase64Integer -> Bool)
, testProperty "JWK round-trip" (prop_roundTrip :: JWK -> Bool)
, testProperty "ECDSA gen, sign and verify" prop_ecSignAndVerify
, testProperty "HMAC gen, sign and verify" prop_hmacSignAndVerify
, testProperty "RSA gen, sign and verify" prop_rsaSignAndVerify
]
prop_roundTrip :: (Eq a, ToJSON a, FromJSON a) => a -> Bool
prop_roundTrip a = decode (encode [a]) == Just [a]
debugRoundTrip
:: (Show a, Arbitrary a, ToJSON a, FromJSON a)
=> (a -> Bool)
-> Property
debugRoundTrip f = monadicIO $ do
a :: a <- pick arbitrary
let encoded = encode [a]
monitor $ counterexample $
"JSON: \n" ++ show encoded ++ "\n\nDecoded: \n" ++ show (decode encoded :: Maybe [a])
assert $ f a
prop_ecSignAndVerify :: Crv -> B.ByteString -> Property
prop_ecSignAndVerify crv msg = monadicIO $ do
k :: JWK <- run $ genJWK (ECGenParam crv)
let alg = case crv of P_256 -> ES256 ; P_384 -> ES384 ; P_521 -> ES512
wp (signJWS (newJWS msg) (newJWSHeader alg) k) (checkSignJWS k)
prop_hmacSignAndVerify :: B.ByteString -> Property
prop_hmacSignAndVerify msg = monadicIO $ do
(alg, minLen) <-
pick $ oneof $ pure <$> [(HS256, 32), (HS384, 48), (HS512, 64)]
keylen <- (+ minLen) <$> pick arbitrarySizedNatural
k :: JWK <- run $ genJWK (OctGenParam keylen)
wp (signJWS (newJWS msg) (newJWSHeader alg) k) (checkSignJWS k)
prop_rsaSignAndVerify :: B.ByteString -> Property
prop_rsaSignAndVerify msg = monadicIO $ do
keylen <- pick $ oneof $ pure . (`div` 8) <$> [2048, 3072, 4096]
k :: JWK <- run $ genJWK (RSAGenParam keylen)
alg <- pick $ oneof $ pure <$> [RS256, RS384, RS512, PS256, PS384, PS512]
wp (signJWS (newJWS msg) (newJWSHeader alg) k) (checkSignJWS k)
checkSignJWS :: (Monad m, Show e) => JWK -> Either e JWS -> PropertyM m ()
checkSignJWS k signResult = case signResult of
Left e -> do
monitor (counterexample $ "Failed to sign: " ++ show e)
assert False
Right jws -> do
monitor (counterexample "Failed to verify")
assert (verifyJWS def def k jws)