Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 1100A107DA for ; Tue, 2 Dec 2014 22:40:07 +0000 (UTC) Received: (qmail 71456 invoked by uid 500); 2 Dec 2014 22:40:07 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 71396 invoked by uid 500); 2 Dec 2014 22:40:06 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 71387 invoked by uid 99); 2 Dec 2014 22:40:06 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 02 Dec 2014 22:40:06 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 8DC159BC774; Tue, 2 Dec 2014 22:40:06 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergeyb@apache.org To: commits@cxf.apache.org Message-Id: <1e4f1d815bc04bb9a30ef08b871da9f1@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: cxf git commit: Prototyping support for JWKs with the certificate info Date: Tue, 2 Dec 2014 22:40:06 +0000 (UTC) Repository: cxf Updated Branches: refs/heads/master 1baae6959 -> a9555675b Prototyping support for JWKs with the certificate info Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/a9555675 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/a9555675 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/a9555675 Branch: refs/heads/master Commit: a9555675b829acdfb1672bc2157d6f3c08fdd652 Parents: 1baae69 Author: Sergey Beryozkin Authored: Tue Dec 2 22:39:47 2014 +0000 Committer: Sergey Beryozkin Committed: Tue Dec 2 22:39:47 2014 +0000 ---------------------------------------------------------------------- .../cxf/common/util/crypto/CryptoUtils.java | 18 ++++++ .../cxf/rs/security/jose/JoseHeaders.java | 8 +-- .../security/jose/jaxrs/KeyManagementUtils.java | 31 ++++++++++ .../cxf/rs/security/jose/jwe/JweUtils.java | 4 +- .../cxf/rs/security/jose/jwk/JsonWebKey.java | 6 +- .../cxf/rs/security/jose/jwk/JwkUtils.java | 62 ++++++++++++++------ .../cxf/rs/security/jose/jws/JwsUtils.java | 4 +- .../rs/security/jose/jwk/JsonWebKeyTest.java | 10 +++- .../cxf/rs/security/jose/jwk/jwkPublicSet.txt | 12 +++- .../jaxrs/security/jwt/JAXRSJweJwsTest.java | 39 ++++++++++++ .../cxf/systest/jaxrs/security/jwt/server.xml | 21 +++++++ .../jaxrs/security/certs/jwkPublicSet.txt | 17 ++++++ .../jaxrs/security/public.jwk.properties | 23 ++++++++ 13 files changed, 224 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/core/src/main/java/org/apache/cxf/common/util/crypto/CryptoUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/cxf/common/util/crypto/CryptoUtils.java b/core/src/main/java/org/apache/cxf/common/util/crypto/CryptoUtils.java index 184f69f..b3017cb 100644 --- a/core/src/main/java/org/apache/cxf/common/util/crypto/CryptoUtils.java +++ b/core/src/main/java/org/apache/cxf/common/util/crypto/CryptoUtils.java @@ -19,6 +19,7 @@ package org.apache.cxf.common.util.crypto; +import java.io.ByteArrayInputStream; import java.io.InputStream; import java.math.BigInteger; import java.security.Key; @@ -31,6 +32,7 @@ import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPrivateKey; @@ -53,6 +55,7 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.common.util.Base64Utility; import org.apache.cxf.common.util.CompressionUtils; import org.apache.cxf.helpers.IOUtils; @@ -628,6 +631,21 @@ public final class CryptoUtils { throw new SecurityException(ex); } } + public static String encodeCertificate(Certificate cert) { + try { + return Base64Utility.encode(cert.getEncoded()); + } catch (Exception ex) { + throw new SecurityException(ex); + } + } + public static Certificate decodeCertificate(String encodedCert) { + try { + byte[] decoded = Base64Utility.decode(encodedCert); + return CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(decoded)); + } catch (Exception ex) { + throw new SecurityException(ex); + } + } public static PublicKey loadPublicKey(InputStream storeLocation, char[] storePassword, String alias, String storeType) { return loadCertificate(storeLocation, storePassword, alias, storeType).getPublicKey(); http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeaders.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeaders.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeaders.java index 60ce970..ac186d2 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeaders.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseHeaders.java @@ -78,12 +78,12 @@ public class JoseHeaders extends JsonMapObject { return (String)getHeader(JoseConstants.HEADER_X509_URL); } - public void setX509Chain(String x509Chain) { - setHeader(JoseConstants.HEADER_X509_CHAIN, x509Chain); + public void setX509Chain(List x509Chain) { + setProperty(JoseConstants.HEADER_X509_CHAIN, x509Chain); } - public String getX509Chain() { - return (String)getHeader(JoseConstants.HEADER_X509_CHAIN); + public List getX509Chain() { + return CastUtils.cast((List)getProperty(JoseConstants.HEADER_X509_CHAIN)); } public void setX509Thumbprint(String x509Thumbprint) { http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/KeyManagementUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/KeyManagementUtils.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/KeyManagementUtils.java index 88fcb3a..cc69b84 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/KeyManagementUtils.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/KeyManagementUtils.java @@ -24,6 +24,9 @@ import java.security.KeyStore; import java.security.Principal; import java.security.PrivateKey; import java.security.PublicKey; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import org.apache.cxf.Bus; @@ -143,4 +146,32 @@ public final class KeyManagementUtils { throw new SecurityException(ex); } } + + public static List encodeX509CertificateChain(List chain) { + List encodedChain = new ArrayList(chain.size()); + for (X509Certificate cert : chain) { + try { + encodedChain.add(CryptoUtils.encodeCertificate(cert)); + } catch (Exception ex) { + throw new SecurityException(ex); + } + } + return encodedChain; + } + public static List toX509CertificateChain(List base64EncodedChain) { + if (base64EncodedChain != null) { + List certs = new ArrayList(base64EncodedChain.size()); + for (String encodedCert : base64EncodedChain) { + try { + certs.add((X509Certificate)CryptoUtils.decodeCertificate(encodedCert)); + } catch (Exception ex) { + throw new SecurityException(ex); + } + } + //TODO: validate the chain + return certs; + } else { + return null; + } + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java index 7f9a8aa..06859f3 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java @@ -112,7 +112,7 @@ public final class JweUtils { String keyEncryptionAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm : jwk.getAlgorithm(); KeyEncryptionAlgorithm keyEncryptionProvider = null; if (JsonWebKey.KEY_TYPE_RSA.equals(jwk.getKeyType())) { - keyEncryptionProvider = getRSAKeyEncryptionAlgorithm(JwkUtils.toRSAPublicKey(jwk), + keyEncryptionProvider = getRSAKeyEncryptionAlgorithm(JwkUtils.toRSAPublicKey(jwk, true), keyEncryptionAlgo); } else if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType())) { keyEncryptionProvider = getSecretKeyEncryptionAlgorithm(JwkUtils.toSecretKey(jwk), @@ -287,7 +287,7 @@ public final class JweUtils { SecretKey ctDecryptionKey = null; String keyEncryptionAlgo = getKeyEncryptionAlgo(props, null); if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) { - JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_ENCRYPT); + JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_DECRYPT); keyEncryptionAlgo = getKeyEncryptionAlgo(props, jwk.getAlgorithm()); if ("direct".equals(keyEncryptionAlgo)) { contentEncryptionAlgo = getContentEncryptionAlgo(props, contentEncryptionAlgo); http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java index 025b248..8566dea 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java @@ -124,12 +124,12 @@ public class JsonWebKey extends JsonMapObject { return (String)getProperty(X509_URL); } - public void setX509Chain(String x509Chain) { + public void setX509Chain(List x509Chain) { setProperty(X509_CHAIN, x509Chain); } - public String getX509Chain() { - return (String)getProperty(X509_CHAIN); + public List getX509Chain() { + return CastUtils.cast((List)getProperty(X509_CHAIN)); } public void setX509Thumbprint(String x509Thumbprint) { http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java index 6d0a2fe..817bdcd 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JwkUtils.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.net.URI; +import java.security.cert.X509Certificate; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPrivateKey; @@ -40,6 +41,7 @@ import org.apache.cxf.common.util.crypto.CryptoUtils; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.jaxrs.utils.ResourceUtils; import org.apache.cxf.message.Message; +import org.apache.cxf.message.MessageUtils; import org.apache.cxf.rs.security.jose.JoseConstants; import org.apache.cxf.rs.security.jose.JoseUtils; import org.apache.cxf.rs.security.jose.jaxrs.KeyManagementUtils; @@ -256,7 +258,7 @@ public final class JwkUtils { public static JsonWebKey loadJsonWebKey(Message m, Properties props, String keyOper, JwkReaderWriter reader) { PrivateKeyPasswordProvider cb = loadPasswordProvider(m, props, keyOper); JsonWebKeys jwkSet = loadJwkSet(m, props, cb, reader); - String kid = getKeyId(props, KeyManagementUtils.RSSEC_KEY_STORE_ALIAS, keyOper); + String kid = getKeyId(m, props, KeyManagementUtils.RSSEC_KEY_STORE_ALIAS, keyOper); if (kid != null) { return jwkSet.getKey(kid); } else if (keyOper != null) { @@ -275,11 +277,11 @@ public final class JwkUtils { JwkReaderWriter reader) { PrivateKeyPasswordProvider cb = loadPasswordProvider(m, props, keyOper); JsonWebKeys jwkSet = loadJwkSet(m, props, cb, reader); - String kid = getKeyId(props, KeyManagementUtils.RSSEC_KEY_STORE_ALIAS, keyOper); + String kid = getKeyId(m, props, KeyManagementUtils.RSSEC_KEY_STORE_ALIAS, keyOper); if (kid != null) { return Collections.singletonList(jwkSet.getKey(kid)); } - String kids = getKeyId(props, KeyManagementUtils.RSSEC_KEY_STORE_ALIASES, keyOper); + String kids = getKeyId(m, props, KeyManagementUtils.RSSEC_KEY_STORE_ALIASES, keyOper); if (kids != null) { String[] values = kids.split(","); List keys = new ArrayList(values.length); @@ -297,9 +299,22 @@ public final class JwkUtils { return null; } public static RSAPublicKey toRSAPublicKey(JsonWebKey jwk) { + return toRSAPublicKey(jwk, false); + } + public static RSAPublicKey toRSAPublicKey(JsonWebKey jwk, boolean checkX509) { String encodedModulus = (String)jwk.getProperty(JsonWebKey.RSA_MODULUS); String encodedPublicExponent = (String)jwk.getProperty(JsonWebKey.RSA_PUBLIC_EXP); - return CryptoUtils.getRSAPublicKey(encodedModulus, encodedPublicExponent); + if (encodedModulus != null) { + return CryptoUtils.getRSAPublicKey(encodedModulus, encodedPublicExponent); + } else if (checkX509) { + List chain = toX509CertificateChain(jwk); + return (RSAPublicKey)chain.get(0).getPublicKey(); + } + return null; + } + public static List toX509CertificateChain(JsonWebKey jwk) { + List base64EncodedChain = jwk.getX509Chain(); + return KeyManagementUtils.toX509CertificateChain(base64EncodedChain); } public static JsonWebKey fromRSAPublicKey(RSAPublicKey pk, String algo) { JsonWebKey jwk = prepareRSAJwk(pk.getModulus(), algo); @@ -307,6 +322,14 @@ public final class JwkUtils { jwk.setProperty(JsonWebKey.RSA_PUBLIC_EXP, encodedPublicExponent); return jwk; } + public static JsonWebKey fromX509CertificateChain(List chain, String algo) { + JsonWebKey jwk = new JsonWebKey(); + jwk.setAlgorithm(algo); + List encodedChain = KeyManagementUtils.encodeX509CertificateChain(chain); + jwk.setX509Chain(encodedChain); + return jwk; + } + public static RSAPrivateKey toRSAPrivateKey(JsonWebKey jwk) { String encodedModulus = (String)jwk.getProperty(JsonWebKey.RSA_MODULUS); String encodedPrivateExponent = (String)jwk.getProperty(JsonWebKey.RSA_PRIVATE_EXP); @@ -363,19 +386,24 @@ public final class JwkUtils { return jwk; } - private static String getKeyId(Properties props, String propertyName, String keyOper) { - String kid = props.getProperty(propertyName); - if (kid == null && keyOper != null) { - String keyIdProp = null; - if (keyOper.equals(JsonWebKey.KEY_OPER_ENCRYPT)) { - keyIdProp = propertyName + ".jwe"; - } else if (keyOper.equals(JsonWebKey.KEY_OPER_SIGN) - || keyOper.equals(JsonWebKey.KEY_OPER_VERIFY)) { - keyIdProp = propertyName + ".jws"; - } - if (keyIdProp != null) { - kid = props.getProperty(keyIdProp); + private static String getKeyId(Message m, Properties props, String preferredPropertyName, String keyOper) { + String kid = null; + String altPropertyName = null; + if (keyOper != null) { + if (keyOper.equals(JsonWebKey.KEY_OPER_ENCRYPT) || keyOper.equals(JsonWebKey.KEY_OPER_DECRYPT)) { + altPropertyName = preferredPropertyName + ".jwe"; + } else if (keyOper.equals(JsonWebKey.KEY_OPER_SIGN) || keyOper.equals(JsonWebKey.KEY_OPER_VERIFY)) { + altPropertyName = preferredPropertyName + ".jws"; } + String direction = m.getExchange().getOutMessage() == m ? ".out" : ".in"; + kid = (String)MessageUtils.getContextualProperty(m, altPropertyName, altPropertyName + direction); + } + + if (kid == null) { + kid = props.getProperty(preferredPropertyName); + } + if (kid == null && altPropertyName != null) { + kid = props.getProperty(altPropertyName); } return kid; } @@ -384,7 +412,7 @@ public final class JwkUtils { (PrivateKeyPasswordProvider)m.getContextualProperty(KeyManagementUtils.RSSEC_KEY_PSWD_PROVIDER); if (cb == null && keyOper != null) { String propName = keyOper.equals(JsonWebKey.KEY_OPER_SIGN) ? KeyManagementUtils.RSSEC_SIG_KEY_PSWD_PROVIDER - : keyOper.equals(JsonWebKey.KEY_OPER_ENCRYPT) + : keyOper.equals(JsonWebKey.KEY_OPER_DECRYPT) ? KeyManagementUtils.RSSEC_DECRYPT_KEY_PSWD_PROVIDER : null; if (propName != null) { cb = (PrivateKeyPasswordProvider)m.getContextualProperty(propName); http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java index 8bab845..e9d228a 100644 --- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java @@ -105,7 +105,7 @@ public final class JwsUtils { String rsaSignatureAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm : jwk.getAlgorithm(); JwsSignatureVerifier theVerifier = null; if (JsonWebKey.KEY_TYPE_RSA.equals(jwk.getKeyType())) { - theVerifier = getRSAKeySignatureVerifier(JwkUtils.toRSAPublicKey(jwk), rsaSignatureAlgo); + theVerifier = getRSAKeySignatureVerifier(JwkUtils.toRSAPublicKey(jwk, true), rsaSignatureAlgo); } else if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType())) { byte[] key = JoseUtils.decode((String)jwk.getProperty(JsonWebKey.OCTET_KEY_VALUE)); theVerifier = getHmacSignatureVerifier(key, rsaSignatureAlgo); @@ -195,7 +195,7 @@ public final class JwsUtils { } List theVerifiers = null; if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) { - List jwks = JwkUtils.loadJsonWebKeys(m, props, JsonWebKey.KEY_OPER_SIGN); + List jwks = JwkUtils.loadJsonWebKeys(m, props, JsonWebKey.KEY_OPER_VERIFY); if (jwks != null) { theVerifiers = new ArrayList(jwks.size()); for (JsonWebKey jwk : jwks) { http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeyTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeyTest.java b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeyTest.java index eb660ae..15ade7d 100644 --- a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeyTest.java +++ b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKeyTest.java @@ -20,6 +20,7 @@ package org.apache.cxf.rs.security.jose.jwk; import java.io.InputStream; import java.security.Security; +import java.security.cert.X509Certificate; import java.util.List; import java.util.Map; @@ -73,7 +74,7 @@ public class JsonWebKeyTest extends Assert { public void testPublicSetAsList() throws Exception { JsonWebKeys jwks = readKeySet("jwkPublicSet.txt"); List keys = jwks.getKeys(); - assertEquals(2, keys.size()); + assertEquals(3, keys.size()); JsonWebKey ecKey = keys.get(0); assertEquals(6, ecKey.asMap().size()); @@ -81,13 +82,18 @@ public class JsonWebKeyTest extends Assert { JsonWebKey rsaKey = keys.get(1); assertEquals(5, rsaKey.asMap().size()); validatePublicRsaKey(rsaKey); + JsonWebKey rsaKeyCert = keys.get(2); + assertEquals(3, rsaKeyCert.asMap().size()); + assertEquals(3, rsaKeyCert.getX509Chain().size()); + List certs = JwkUtils.toX509CertificateChain(rsaKeyCert); + assertEquals(3, certs.size()); } @Test public void testPublicSetAsMap() throws Exception { JsonWebKeys jwks = readKeySet("jwkPublicSet.txt"); Map keysMap = jwks.getKeyIdMap(); - assertEquals(2, keysMap.size()); + assertEquals(3, keysMap.size()); JsonWebKey rsaKey = keysMap.get(RSA_KID_VALUE); assertEquals(5, rsaKey.asMap().size()); http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/jwkPublicSet.txt ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/jwkPublicSet.txt b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/jwkPublicSet.txt index 5a4a839..2fd93f6 100644 --- a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/jwkPublicSet.txt +++ b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/jwkPublicSet.txt @@ -11,7 +11,17 @@ "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", "e":"AQAB", "alg":"RS256", - "kid":"2011-04-29"} + "kid":"2011-04-29"}, + + { + "kty":"RSA", + "kid":"RSACerts", + "x5c": [ + "MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYwMTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3HKrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQmVZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpRSgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRTcDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEuMB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDSkdRMEXGzYcs9of7dqGrU4zA SBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUHAgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IGOgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMUA2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTXRE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuHqDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWVU+4=", + "MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoXDTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHUTBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMbVmFsaUNlcnQgVmFsaWRhdGl vbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwgSW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlvbiBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEgMB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUwAwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdvZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUdIAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4OWBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0VmsfSxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==", + "MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7 tdEy8W9ViH0Pd" + ] + } ] } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java index c451657..08ea2cc 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/JAXRSJweJwsTest.java @@ -33,6 +33,7 @@ import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; import org.apache.cxf.Bus; import org.apache.cxf.bus.spring.SpringBusFactory; import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean; +import org.apache.cxf.jaxrs.client.WebClient; import org.apache.cxf.rs.security.jose.jaxrs.JweClientResponseFilter; import org.apache.cxf.rs.security.jose.jaxrs.JweWriterInterceptor; import org.apache.cxf.rs.security.jose.jaxrs.JwsClientResponseFilter; @@ -59,6 +60,8 @@ public class JAXRSJweJwsTest extends AbstractBusClientServerTestBase { "org/apache/cxf/systest/jaxrs/security/bob.rs.properties"; private static final String SERVER_JWEJWS_PROPERTIES = "org/apache/cxf/systest/jaxrs/security/alice.rs.properties"; + private static final String PUBLIC_JWEJWS_PROPERTIES = + "org/apache/cxf/systest/jaxrs/security/public.jwk.properties"; private static final String ENCODED_MAC_KEY = "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75" + "aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"; @BeforeClass @@ -182,6 +185,42 @@ public class JAXRSJweJwsTest extends AbstractBusClientServerTestBase { assertEquals("book", text); } @Test + public void testJweRsaJwsRsaCert() throws Exception { + String address = "https://localhost:" + PORT + "/jwejwsrsacert"; + + JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); + SpringBusFactory bf = new SpringBusFactory(); + URL busFile = JAXRSJweJwsTest.class.getResource("client.xml"); + Bus springBus = bf.createBus(busFile.toString()); + bean.setBus(springBus); + bean.setServiceClass(BookStore.class); + bean.setAddress(address); + List providers = new LinkedList(); + JweWriterInterceptor jweWriter = new JweWriterInterceptor(); + jweWriter.setUseJweOutputStream(true); + providers.add(jweWriter); + providers.add(new JweClientResponseFilter()); + JwsWriterInterceptor jwsWriter = new JwsWriterInterceptor(); + jwsWriter.setUseJwsOutputStream(true); + providers.add(jwsWriter); + providers.add(new JwsClientResponseFilter()); + + bean.setProviders(providers); + bean.getProperties(true).put("rs.security.encryption.out.properties", PUBLIC_JWEJWS_PROPERTIES); + bean.getProperties(true).put("rs.security.signature.out.properties", CLIENT_JWEJWS_PROPERTIES); + bean.getProperties(true).put("rs.security.encryption.in.properties", CLIENT_JWEJWS_PROPERTIES); + bean.getProperties(true).put("rs.security.signature.in.properties", PUBLIC_JWEJWS_PROPERTIES); + PrivateKeyPasswordProvider provider = new PrivateKeyPasswordProviderImpl(); + bean.getProperties(true).put("rs.security.signature.key.password.provider", provider); + bean.getProperties(true).put("rs.security.decryption.key.password.provider", provider); + BookStore bs = bean.create(BookStore.class); + + WebClient.getConfig(bs).getRequestContext().put("rs.security.keystore.alias.jwe.out", "AliceCert"); + WebClient.getConfig(bs).getRequestContext().put("rs.security.keystore.alias.jws.in", "AliceCert"); + String text = bs.echoText("book"); + assertEquals("book", text); + } + @Test public void testJweRsaJwsPlainTextHMac() throws Exception { String address = "https://localhost:" + PORT + "/jwejwshmac"; HmacJwsSignatureProvider hmacProvider = http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/server.xml ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/server.xml b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/server.xml index 0ba3a5a..d357cb9 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/server.xml +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/jwt/server.xml @@ -98,6 +98,27 @@ under the License. + + + + + + + + + + + + + + + + + + + + + http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/certs/jwkPublicSet.txt ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/certs/jwkPublicSet.txt b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/certs/jwkPublicSet.txt index 6ecc25e..3e1f6a2 100644 --- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/certs/jwkPublicSet.txt +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/certs/jwkPublicSet.txt @@ -10,5 +10,22 @@ "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", "use":"enc", "kid":"ECKey"}, + + { + "kty":"RSA", + "kid":"AliceCert", + "x5c": [ + "MIICGjCCAYOgAwIBAgIESVRgATANBgkqhkiG9w0BAQUFADAzMRMwEQYDVQQKEwphcGFjaGUub3JnMQwwCgYDVQQLEwNlbmcxDjAMBgNVBAMTBWN4ZmNhMB4XDTcwMDEwMTAwMDAwMFoXDTM4MDExOTAzMTQwN1owMzETMBEGA1UEChMKYXBhY2hlLm9yZzEMMAoGA1UECxMDZW5nMQ4wDAYDVQQDEwVhbGljZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvu747/VShQ85f16DGSc4Ixh9PVpGguyEqrCsK8q9XHOYX9l9/g5wEC6ZcR2FwfNsoaHcKNPjd5sSTzVtBWmQjfBEfIqwTR7vuihOxyNTwEzVwIJzvo7p8/aYxk+VdBtQxq4UweIcf/iFkUbM1cZ1oiXRQzciRBi+C1BQCQE0qzsCAwEAAaM7MDkwIQYDVR0SBBowGIIWTk9UX0ZPUl9QUk9EVUNUSU9OX1VTRTAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJKoZIhvcNAQEFBQADgYEAhLwkm+8psKt4gnbikGzV0TgpSWGcWxWKBi+z8tI2n6hFA5v1jVHHa4G9h3s0nxQ2TewzeR/k7gmgV2sI483NgrYHmTmLKaDBWza2pAuZuDhQH8GAEhJakFtKBP++EC9rNNpZnqqHxx3qb2tW25qRtBzDmK921gg9PMomMc7uqRQ=" + ] + }, + + { + "kty":"RSA", + "kid":"BobCert", + "x5c": [ + "MIICGDCCAYGgAwIBAgIESVRgAjANBgkqhkiG9w0BAQUFADAzMRMwEQYDVQQKEwphcGFjaGUub3JnMQwwCgYDVQQLEwNlbmcxDjAMBgNVBAMTBWN4ZmNhMB4XDTcwMDEwMTAwMDAwMFoXDTM4MDExOTAzMTQwN1owMTETMBEGA1UEChMKYXBhY2hlLm9yZzEMMAoGA1UECxMDZW5nMQwwCgYDVQQDEwNib2IwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIUcy5V9ow7xb1GOI+5ub1YIApEvw7JSySBdYv9eeVFVG/c0Sxoqcwmlc0tJcxF1K2hEcXL4Na9hWkzmLO3QAzEKGseLsXXTGinFaXW3RL7lOXuJ6bbWsosF+YIv0fHqS1ZHREd2KAou1GWiAP9Stu0JiOQF211eRo+RZisQkDwvAgMBAAGjOzA5MCEGA1UdEgQaMBiCFk5PVF9GT1JfUFJPRFVDVElPTl9VU0UwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBBQUAA4GBAFncwiuc44aCHD8IJ8/t4hmCZzqi+2O33E7OkHQz83R5Vs9YHt+ZkIO9vvnwhq1vcq68HNlG1e+wbeIyde58zYLcUZN5qZxHNchj0Hb70BmBQqYEd7C9SXtluJDguinQpkSTyJ1Nt0tx7ropBq/l43LGuca5isD4yx/JAhnm1469" + ] + } + ] } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/a9555675/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/public.jwk.properties ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/public.jwk.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/public.jwk.properties new file mode 100644 index 0000000..6cb973e --- /dev/null +++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/public.jwk.properties @@ -0,0 +1,23 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# +rs.security.keystore.type=jwk +rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/jwkPublicSet.txt +rs.security.jwe.content.encryption.algorithm=A128GCM +rs.security.jwe.key.encryption.algorithm=RSA-OAEP +rs.security.jws.content.signature.algorithm=RS256