packages feed

jose-jwt 0.7.8 → 0.8.0

raw patch · 8 files changed

+58/−31 lines, 8 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Jose.Jwa: RSA_OAEP_256 :: JweAlg
- Jose.Jwt: decodeClaims :: ByteString -> Either JwtError (JwtHeader, JwtClaims)
+ Jose.Jwt: decodeClaims :: (FromJSON a) => ByteString -> Either JwtError (JwtHeader, a)

Files

CHANGELOG.md view
@@ -1,3 +1,11 @@+0.8.0+-----++* The result of the `Jose.Jwt.decodeClaims` function is now polymorphic so it can be used with+any `FromJSON` type.+* Only ghc 8 upwards are now supported.+* the RSA-OAEP-256 algorithm is now supported.+ 0.7.8 ----- 
Jose/Internal/Crypto.hs view
@@ -155,15 +155,16 @@     => RSA.PublicKey     -- ^ The encryption key     -> JweAlg-    -- ^ The algorithm (either @RSA1_5@ or @RSA_OAEP@)+    -- ^ The algorithm (@RSA1_5@, @RSA_OAEP@, or @RSA_OAEP_256@)     -> msg     -- ^ The message to encrypt     -> m (Either JwtError out)     -- ^ The encrypted message rsaEncrypt k a msg = fmap BA.convert <$> case a of-    RSA1_5   -> mapErr (PKCS15.encrypt k bs)-    RSA_OAEP -> mapErr (OAEP.encrypt (OAEP.defaultOAEPParams SHA1) k bs)-    _        -> return (Left (BadAlgorithm "Not an RSA algorithm"))+    RSA1_5       -> mapErr (PKCS15.encrypt k bs)+    RSA_OAEP     -> mapErr (OAEP.encrypt (OAEP.defaultOAEPParams SHA1) k bs)+    RSA_OAEP_256 -> mapErr (OAEP.encrypt (OAEP.defaultOAEPParams SHA256) k bs)+    _            -> return (Left (BadAlgorithm "Not an RSA algorithm"))   where     bs = BA.convert msg     mapErr = fmap (mapLeft (const BadCrypto))@@ -180,9 +181,10 @@     -> Either JwtError ScrubbedBytes     -- ^ The decrypted key rsaDecrypt blinder rsaKey a ct = BA.convert <$> case a of-    RSA1_5   -> mapErr (PKCS15.decrypt blinder rsaKey bs)-    RSA_OAEP -> mapErr (OAEP.decrypt blinder (OAEP.defaultOAEPParams SHA1) rsaKey bs)-    _        -> Left (BadAlgorithm "Not an RSA algorithm")+    RSA1_5       -> mapErr (PKCS15.decrypt blinder rsaKey bs)+    RSA_OAEP     -> mapErr (OAEP.decrypt blinder (OAEP.defaultOAEPParams SHA1) rsaKey bs)+    RSA_OAEP_256 -> mapErr (OAEP.decrypt blinder (OAEP.defaultOAEPParams SHA256) rsaKey bs)+    _            -> Left (BadAlgorithm "Not an RSA algorithm")   where     bs = BA.convert ct     mapErr = mapLeft (const BadCrypto)
Jose/Jwa.hs view
@@ -24,14 +24,14 @@  -- | A subset of the key management algorithms from the -- <https://tools.ietf.org/html/rfc7518#section-4 JWA Spec>.-data JweAlg = RSA1_5 | RSA_OAEP | A128KW | A192KW | A256KW deriving (Eq, Show, Read)+data JweAlg = RSA1_5 | RSA_OAEP | RSA_OAEP_256 | A128KW | A192KW | A256KW deriving (Eq, Show, Read)  -- | Content encryption algorithms from the -- <https://tools.ietf.org/html/rfc7518#section-5 JWA Spec>. data Enc = A128CBC_HS256 | A192CBC_HS384 | A256CBC_HS512 | A128GCM | A192GCM | A256GCM deriving (Eq, Show)  algs :: [(Text, Alg)]-algs = [("none", Signed None), ("HS256", Signed HS256), ("HS384", Signed HS384), ("HS512", Signed HS512), ("RS256", Signed RS256), ("RS384", Signed RS384), ("RS512", Signed RS512), ("ES256", Signed ES256), ("ES384", Signed ES384), ("ES512", Signed ES512), ("RSA1_5", Encrypted RSA1_5), ("RSA-OAEP", Encrypted RSA_OAEP), ("A128KW", Encrypted A128KW), ("A192KW", Encrypted A192KW), ("A256KW", Encrypted A256KW)]+algs = [("none", Signed None), ("HS256", Signed HS256), ("HS384", Signed HS384), ("HS512", Signed HS512), ("RS256", Signed RS256), ("RS384", Signed RS384), ("RS512", Signed RS512), ("ES256", Signed ES256), ("ES384", Signed ES384), ("ES512", Signed ES512), ("RSA1_5", Encrypted RSA1_5), ("RSA-OAEP", Encrypted RSA_OAEP), ("RSA-OAEP-256", Encrypted RSA_OAEP_256), ("A128KW", Encrypted A128KW), ("A192KW", Encrypted A192KW), ("A256KW", Encrypted A256KW)]  algName :: Alg -> Text algName a = let Just n = lookup a algNames in n
Jose/Jwk.hs view
@@ -2,7 +2,8 @@ {-# OPTIONS_HADDOCK prune #-}  module Jose.Jwk-    ( KeyUse (..)+    ( EcCurve (..)+    , KeyUse (..)     , KeyId     , Jwk (..)     , JwkSet (..)@@ -136,24 +137,27 @@     keyIdCompatible (jweKid hdr) jwk &&     algCompatible (Encrypted (jweAlg hdr)) jwk &&     case (jweAlg hdr, jwk) of-        (RSA1_5,   RsaPrivateJwk {}) -> True-        (RSA_OAEP, RsaPrivateJwk {}) -> True-        (A128KW,   SymmetricJwk k _ _ _) -> B.length k == 16-        (A192KW,   SymmetricJwk k _ _ _) -> B.length k == 24-        (A256KW,   SymmetricJwk k _ _ _) -> B.length k == 32+        (RSA1_5,       RsaPrivateJwk {}) -> True+        (RSA_OAEP,     RsaPrivateJwk {}) -> True+        (RSA_OAEP_256, RsaPrivateJwk {}) -> True+        (A128KW,       SymmetricJwk k _ _ _) -> B.length k == 16+        (A192KW,       SymmetricJwk k _ _ _) -> B.length k == 24+        (A256KW,       SymmetricJwk k _ _ _) -> B.length k == 32         _                            -> False  canEncodeJwe :: JweAlg -> Jwk -> Bool canEncodeJwe a jwk = jwkUse jwk /= Just Sig &&     algCompatible (Encrypted a) jwk &&     case (a, jwk) of-        (RSA1_5,   RsaPublicJwk {})  -> True-        (RSA_OAEP, RsaPublicJwk {})  -> True-        (RSA1_5,   RsaPrivateJwk {}) -> True-        (RSA_OAEP, RsaPrivateJwk {}) -> True-        (A128KW,   SymmetricJwk k _ _ _) -> B.length k == 16-        (A192KW,   SymmetricJwk k _ _ _) -> B.length k == 24-        (A256KW,   SymmetricJwk k _ _ _) -> B.length k == 32+        (RSA1_5,       RsaPublicJwk {})  -> True+        (RSA_OAEP,     RsaPublicJwk {})  -> True+        (RSA_OAEP_256, RsaPublicJwk {})  -> True+        (RSA1_5,       RsaPrivateJwk {}) -> True+        (RSA_OAEP,     RsaPrivateJwk {}) -> True+        (RSA_OAEP_256, RsaPrivateJwk {}) -> True+        (A128KW,       SymmetricJwk k _ _ _) -> B.length k == 16+        (A192KW,       SymmetricJwk k _ _ _) -> B.length k == 24+        (A256KW,       SymmetricJwk k _ _ _) -> B.length k == 32         _                            -> False  keyIdCompatible :: Maybe KeyId -> Jwk -> Bool
Jose/Jwt.hs view
@@ -33,7 +33,7 @@ import qualified Crypto.PubKey.ECC.ECDSA as ECDSA import Crypto.PubKey.RSA (PrivateKey(..)) import Crypto.Random (MonadRandom)-import Data.Aeson (decodeStrict')+import Data.Aeson (decodeStrict',FromJSON) import Data.ByteString (ByteString) import Data.Maybe (isNothing) import qualified Data.ByteString.Char8 as BC@@ -122,14 +122,17 @@     checkKeys ks = return ks  --- | Convenience function to return the claims contained in a JWT.--- This is required in situations such as client assertion authentication,--- where the contents of the JWT may be required in order to work out+-- | Convenience function to return the claims contained in a JWS.+-- This is needed in situations such as client assertion authentication,+-- <https://tools.ietf.org/html/rfc7523>, where the contents of the JWT,+-- such as the @sub@ claim, may be required in order to work out -- which key should be used to verify the token.+-- -- Obviously this should not be used by itself to decode a token since -- no integrity checking is done and the contents may be forged.-decodeClaims :: ByteString-             -> Either JwtError (JwtHeader, JwtClaims)+decodeClaims :: (FromJSON a)+    => ByteString+    -> Either JwtError (JwtHeader, a) decodeClaims jwt = do     let components = BC.split '.' jwt     when (length components /= 3) $ Left $ BadDots 2
jose-jwt.cabal view
@@ -1,5 +1,5 @@ Name:               jose-jwt-Version:            0.7.8+Version:            0.8.0 Synopsis:           JSON Object Signing and Encryption Library Homepage:           http://github.com/tekul/jose-jwt Bug-Reports:        http://github.com/tekul/jose-jwt/issues@@ -44,7 +44,11 @@                     , Jose.Internal.Crypto                     , Jose.Internal.Parser   Other-Modules:      Jose.Types-  Build-Depends:      base >= 4.6 && < 5++  if impl(ghc < 8.0)+    Buildable: False+  else+    Build-depends:    base                     , aeson >= 0.8.0.2                     , attoparsec >= 0.12.0.0                     , bytestring >= 0.9
tests/Tests/JweSpec.hs view
@@ -291,7 +291,7 @@  instance Arbitrary JWEAlgs where   arbitrary = do-    a <- elements [RSA1_5, RSA_OAEP, A128KW, A192KW, A256KW]+    a <- elements [RSA1_5, RSA_OAEP, RSA_OAEP_256, A128KW, A192KW, A256KW]     e <- arbitrary     return $ JWEAlgs a e 
tests/Tests/JwsSpec.hs view
@@ -57,6 +57,10 @@           let Just k21 = decodeStrict' a21jwk           fstWithRNG (decode [k21] (Just (JwsEncoding RS256)) a21) @?= (Right $ Jws (defJwsHdr {jwsAlg = RS256}, a21Payload)) +        it "decodes the successfully without verification" $ do+           let Right (_, claims) = decodeClaims a21 :: Either JwtError (JwtHeader, JwtClaims)+           jwtIss claims @?= Just "joe"+         it "encodes the payload to the expected JWT" $ do           let sign = either (error "Sign failed") id . RSAPKCS15.sign Nothing (Just SHA256) rsaPrivateKey           signWithHeader sign a21Header a21Payload @?= a21@@ -69,6 +73,8 @@          it "encodes/decodes using RS512" $           rsaRoundTrip RS512 a21Payload++        context "when using JWS Appendix A.3 data" $ do         let a31decoded = Right (defJwsHdr {jwsAlg = ES256}, a31Payload)