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 +8/−0
- Jose/Internal/Crypto.hs +9/−7
- Jose/Jwa.hs +2/−2
- Jose/Jwk.hs +17/−13
- Jose/Jwt.hs +9/−6
- jose-jwt.cabal +6/−2
- tests/Tests/JweSpec.hs +1/−1
- tests/Tests/JwsSpec.hs +6/−0
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)