You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2014/12/02 23:40:06 UTC

cxf git commit: Prototyping support for JWKs with the certificate info

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 <sb...@talend.com>
Authored: Tue Dec 2 22:39:47 2014 +0000
Committer: Sergey Beryozkin <sb...@talend.com>
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<String> x509Chain) {
+        setProperty(JoseConstants.HEADER_X509_CHAIN, x509Chain);
     }
 
-    public String getX509Chain() {
-        return (String)getHeader(JoseConstants.HEADER_X509_CHAIN);
+    public List<String> 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<String> encodeX509CertificateChain(List<X509Certificate> chain) {
+        List<String> encodedChain = new ArrayList<String>(chain.size());
+        for (X509Certificate cert : chain) {
+            try {
+                encodedChain.add(CryptoUtils.encodeCertificate(cert));
+            } catch (Exception ex) {
+                throw new SecurityException(ex);
+            }    
+        }
+        return encodedChain;
+    }
+    public static List<X509Certificate> toX509CertificateChain(List<String> base64EncodedChain) {
+        if (base64EncodedChain != null) {
+            List<X509Certificate> certs = new ArrayList<X509Certificate>(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<String> x509Chain) {
         setProperty(X509_CHAIN, x509Chain);
     }
 
-    public String getX509Chain() {
-        return (String)getProperty(X509_CHAIN);
+    public List<String> 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<JsonWebKey> keys = new ArrayList<JsonWebKey>(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<X509Certificate> chain = toX509CertificateChain(jwk);
+            return (RSAPublicKey)chain.get(0).getPublicKey();
+        }
+        return null;
+    }
+    public static List<X509Certificate> toX509CertificateChain(JsonWebKey jwk) {
+        List<String> 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<X509Certificate> chain, String algo) {
+        JsonWebKey jwk = new JsonWebKey();
+        jwk.setAlgorithm(algo);
+        List<String> 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<JwsSignatureVerifier> theVerifiers = null; 
         if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
-            List<JsonWebKey> jwks = JwkUtils.loadJsonWebKeys(m, props, JsonWebKey.KEY_OPER_SIGN);
+            List<JsonWebKey> jwks = JwkUtils.loadJsonWebKeys(m, props, JsonWebKey.KEY_OPER_VERIFY);
             if (jwks != null) {
                 theVerifiers = new ArrayList<JwsSignatureVerifier>(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<JsonWebKey> 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<X509Certificate> certs = JwkUtils.toX509CertificateChain(rsaKeyCert);
+        assertEquals(3, certs.size());
     }
     
     @Test
     public void testPublicSetAsMap() throws Exception {
         JsonWebKeys jwks = readKeySet("jwkPublicSet.txt");
         Map<String, JsonWebKey> 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<Object> providers = new LinkedList<Object>();
+        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.
             <entry key="rs.security.decryption.key.password.provider" value-ref="keyPasswordProvider"/>
         </jaxrs:properties>
     </jaxrs:server>
+    <jaxrs:server address="https://localhost:${testutil.ports.jaxrs-jwt}/jwejwsrsacert">
+        <jaxrs:serviceBeans>
+            <ref bean="serviceBean"/>
+        </jaxrs:serviceBeans>
+        <jaxrs:providers>
+            <ref bean="jweInFilter"/>
+            <ref bean="jweOutFilter"/>
+            <ref bean="jwsInFilter"/>
+            <ref bean="jwsOutFilter"/>
+        </jaxrs:providers>
+        <jaxrs:properties>
+            <entry key="rs.security.encryption.in.properties" value="org/apache/cxf/systest/jaxrs/security/alice.rs.properties"/>
+            <entry key="rs.security.signature.in.properties" value="org/apache/cxf/systest/jaxrs/security/public.jwk.properties"/>
+            <entry key="rs.security.encryption.out.properties" value="org/apache/cxf/systest/jaxrs/security/public.jwk.properties"/>
+            <entry key="rs.security.signature.out.properties" value="org/apache/cxf/systest/jaxrs/security/alice.rs.properties"/>
+            <entry key="rs.security.keystore.alias.jwe.out" value="BobCert"/>
+            <entry key="rs.security.keystore.alias.jws.in" value="BobCert"/>
+            <entry key="rs.security.signature.key.password.provider" value-ref="keyPasswordProvider"/>
+            <entry key="rs.security.decryption.key.password.provider" value-ref="keyPasswordProvider"/>
+        </jaxrs:properties>
+    </jaxrs:server>
     <bean id="jackson" class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider"/>
     <jaxrs:server address="https://localhost:${testutil.ports.jaxrs-jwt}/jwejwkrsa">
         <jaxrs:serviceBeans>

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