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 2015/02/02 23:12:01 UTC

cxf git commit: Prototyping the code for supporting passing public keys/certs in the jose headers

Repository: cxf
Updated Branches:
  refs/heads/master 96ed80508 -> 5e919271e


Prototyping the code for supporting passing public keys/certs in the jose headers


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/5e919271
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/5e919271
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/5e919271

Branch: refs/heads/master
Commit: 5e919271e2e92f9845d6454b37ab0b86cfc66591
Parents: 96ed805
Author: Sergey Beryozkin <sb...@talend.com>
Authored: Mon Feb 2 22:11:44 2015 +0000
Committer: Sergey Beryozkin <sb...@talend.com>
Committed: Mon Feb 2 22:11:44 2015 +0000

----------------------------------------------------------------------
 .../jose/jaxrs/AbstractJweDecryptingFilter.java | 10 +--
 .../jose/jaxrs/AbstractJwsReaderProvider.java   |  5 +-
 .../jose/jaxrs/AbstractJwsWriterProvider.java   |  4 +-
 .../jose/jaxrs/JweWriterInterceptor.java        | 20 +++---
 .../jose/jaxrs/JwsClientResponseFilter.java     |  2 +-
 .../jose/jaxrs/JwsContainerRequestFilter.java   |  2 +-
 .../jose/jaxrs/JwtJwsAuthenticationFilter.java  |  2 +-
 .../security/jose/jaxrs/KeyManagementUtils.java | 65 +++++++++++++++++--
 .../cxf/rs/security/jose/jwe/JweUtils.java      | 63 +++++++++++++-----
 .../cxf/rs/security/jose/jwk/JwkUtils.java      | 13 ++++
 .../cxf/rs/security/jose/jws/JwsUtils.java      | 67 +++++++++++++++-----
 .../jaxrs/security/jwt/JAXRSJweJwsTest.java     |  8 +++
 .../cxf/systest/jaxrs/security/jwt/server.xml   | 19 ++++++
 .../security/alice.rs.storeonly.properties      | 19 ++++++
 .../jaxrs/security/bob.rs.storeonly.properties  | 21 ++++++
 15 files changed, 258 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java
index 03c024e..0d7d915 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJweDecryptingFilter.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.io.InputStream;
 
 import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.rs.security.jose.jwe.JweCompactConsumer;
 import org.apache.cxf.rs.security.jose.jwe.JweDecryptionOutput;
 import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider;
 import org.apache.cxf.rs.security.jose.jwe.JweHeaders;
@@ -31,8 +32,9 @@ public class AbstractJweDecryptingFilter {
     private JweDecryptionProvider decryption;
     private String defaultMediaType;
     protected JweDecryptionOutput decrypt(InputStream is) throws IOException {
-        JweDecryptionProvider theDecryptor = getInitializedDecryptionProvider();
-        JweDecryptionOutput out = theDecryptor.decrypt(new String(IOUtils.readBytesFromStream(is), "UTF-8"));
+        JweCompactConsumer jwe = new JweCompactConsumer(new String(IOUtils.readBytesFromStream(is), "UTF-8"));
+        JweDecryptionProvider theDecryptor = getInitializedDecryptionProvider(jwe.getJweHeaders());
+        JweDecryptionOutput out = new JweDecryptionOutput(jwe.getJweHeaders(), jwe.getDecryptedContent(theDecryptor));
         validateHeaders(out.getHeaders());
         return out;
     }
@@ -43,11 +45,11 @@ public class AbstractJweDecryptingFilter {
     public void setDecryptionProvider(JweDecryptionProvider decryptor) {
         this.decryption = decryptor;
     }
-    protected JweDecryptionProvider getInitializedDecryptionProvider() {
+    protected JweDecryptionProvider getInitializedDecryptionProvider(JweHeaders headers) {
         if (decryption != null) {
             return decryption;    
         } 
-        return JweUtils.loadDecryptionProvider(true);
+        return JweUtils.loadDecryptionProvider(headers, true);
     }
     public String getDefaultMediaType() {
         return defaultMediaType;

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java
index 441f4bb..90d6c74 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsReaderProvider.java
@@ -18,6 +18,7 @@
  */
 package org.apache.cxf.rs.security.jose.jaxrs;
 
+import org.apache.cxf.rs.security.jose.JoseHeaders;
 import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
 import org.apache.cxf.rs.security.jose.jws.JwsUtils;
 
@@ -29,11 +30,11 @@ public class AbstractJwsReaderProvider {
         this.sigVerifier = signatureVerifier;
     }
 
-    protected JwsSignatureVerifier getInitializedSigVerifier() {
+    protected JwsSignatureVerifier getInitializedSigVerifier(JoseHeaders headers) {
         if (sigVerifier != null) {
             return sigVerifier;    
         } 
-        return JwsUtils.loadSignatureVerifier(true);
+        return JwsUtils.loadSignatureVerifier(headers, true);
     }
 
     public String getDefaultMediaType() {

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java
index 1fc5bdc..02f5390 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java
@@ -42,9 +42,7 @@ public class AbstractJwsWriterProvider {
         if (sigProvider != null) {
             return sigProvider;    
         } 
-        JwsSignatureProvider theSigProvider = JwsUtils.loadSignatureProvider(true); 
-        headers.setAlgorithm(theSigProvider.getAlgorithm());
-        return theSigProvider;
+        return JwsUtils.loadSignatureProvider(headers, true); 
     }
     protected void setRequestContextProperty(JoseHeaders headers) {    
         JoseUtils.setJoseContextProperty(headers);

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java
index cc28c63..36a2c51 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JweWriterInterceptor.java
@@ -21,7 +21,6 @@ package org.apache.cxf.rs.security.jose.jaxrs;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.Collections;
 import java.util.zip.DeflaterOutputStream;
 
 import javax.annotation.Priority;
@@ -54,8 +53,8 @@ public class JweWriterInterceptor implements WriterInterceptor {
             return;
         }
         OutputStream actualOs = ctx.getOutputStream();
-        
-        JweEncryptionProvider theEncryptionProvider = getInitializedEncryptionProvider();
+        JweHeaders jweHeaders = new JweHeaders();
+        JweEncryptionProvider theEncryptionProvider = getInitializedEncryptionProvider(jweHeaders);
         
         String ctString = null;
         MediaType contentMediaType = ctx.getMediaType();
@@ -66,9 +65,12 @@ public class JweWriterInterceptor implements WriterInterceptor {
                 ctString = JAXRSUtils.mediaTypeToString(contentMediaType);
             }
         }
+        if (ctString != null) {
+            jweHeaders.setContentType(ctString);
+        }
         
         if (useJweOutputStream) {
-            JweEncryptionState encryption = theEncryptionProvider.createJweEncryptionState(toJweHeaders(ctString));
+            JweEncryptionState encryption = theEncryptionProvider.createJweEncryptionState(jweHeaders);
             try {
                 JweCompactProducer.startJweContent(actualOs,
                                                    encryption.getHeaders(), 
@@ -93,7 +95,7 @@ public class JweWriterInterceptor implements WriterInterceptor {
             CachedOutputStream cos = new CachedOutputStream(); 
             ctx.setOutputStream(cos);
             ctx.proceed();
-            String jweContent = theEncryptionProvider.encrypt(cos.getBytes(), toJweHeaders(ctString));
+            String jweContent = theEncryptionProvider.encrypt(cos.getBytes(), jweHeaders);
             setJoseMediaType(ctx);
             IOUtils.copy(new ByteArrayInputStream(StringUtils.toBytesUTF8(jweContent)), 
                          actualOs);
@@ -106,11 +108,11 @@ public class JweWriterInterceptor implements WriterInterceptor {
         ctx.setMediaType(joseMediaType);
     }
     
-    protected JweEncryptionProvider getInitializedEncryptionProvider() {
+    protected JweEncryptionProvider getInitializedEncryptionProvider(JweHeaders headers) {
         if (encryptionProvider != null) {
             return encryptionProvider;    
         } 
-        return JweUtils.loadEncryptionProvider(true);
+        return JweUtils.loadEncryptionProvider(headers, true);
     }
     
     public void setUseJweOutputStream(boolean useJweOutputStream) {
@@ -120,7 +122,5 @@ public class JweWriterInterceptor implements WriterInterceptor {
     public void setEncryptionProvider(JweEncryptionProvider encryptionProvider) {
         this.encryptionProvider = encryptionProvider;
     }
-    private static JweHeaders toJweHeaders(String ct) {
-        return new JweHeaders(Collections.<String, Object>singletonMap(JoseConstants.HEADER_CONTENT_TYPE, ct));
-    }
+    
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsClientResponseFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsClientResponseFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsClientResponseFilter.java
index 840c971..46a5813 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsClientResponseFilter.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsClientResponseFilter.java
@@ -35,8 +35,8 @@ import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
 public class JwsClientResponseFilter extends AbstractJwsReaderProvider implements ClientResponseFilter {
     @Override
     public void filter(ClientRequestContext req, ClientResponseContext res) throws IOException {
-        JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier();
         JwsCompactConsumer p = new JwsCompactConsumer(IOUtils.readStringFromStream(res.getEntityStream()));
+        JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier(p.getJoseHeaders());
         if (!p.verifySignatureWith(theSigVerifier)) {
             throw new SecurityException();
         }

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
index 6164b8f..6eb15e4 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
@@ -41,8 +41,8 @@ public class JwsContainerRequestFilter extends AbstractJwsReaderProvider impleme
         if (HttpMethod.GET.equals(context.getMethod())) {
             return;
         }
-        JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier();
         JwsCompactConsumer p = new JwsCompactConsumer(IOUtils.readStringFromStream(context.getEntityStream()));
+        JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier(p.getJoseHeaders());
         if (!p.verifySignatureWith(theSigVerifier)) {
             context.abortWith(JAXRSUtils.toResponse(400));
             return;

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtJwsAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtJwsAuthenticationFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtJwsAuthenticationFilter.java
index 68d222f..bf1754c 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtJwsAuthenticationFilter.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtJwsAuthenticationFilter.java
@@ -47,8 +47,8 @@ public class JwtJwsAuthenticationFilter extends AbstractJwsReaderProvider implem
             throw new SecurityException();
         }
         
-        JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier();
         JwsJwtCompactConsumer p = new JwsJwtCompactConsumer(schemeData[1]);
+        JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier(p.getJoseHeaders());
         if (!p.verifySignatureWith(theSigVerifier)) {
             context.abortWith(JAXRSUtils.toResponse(400));
             return;

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/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 58869d8..a798dec 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,8 +24,12 @@ import java.security.KeyStore;
 import java.security.Principal;
 import java.security.PrivateKey;
 import java.security.PublicKey;
+import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPrivateKey;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
 import java.util.List;
 import java.util.Properties;
 
@@ -54,9 +58,31 @@ public final class KeyManagementUtils {
     public static final String RSSEC_SIG_KEY_PSWD_PROVIDER = "rs.security.signature.key.password.provider";
     public static final String RSSEC_DECRYPT_KEY_PSWD_PROVIDER = "rs.security.decryption.key.password.provider";
     public static final String RSSEC_DEFAULT_ALGORITHMS = "rs.security.default.algorithms";
+    public static final String RSSEC_REPORT_KEY_PROP = "rs.security.report.public.key";
     
     private KeyManagementUtils() {
     }
+    public static List<String> loadAndEncodeX509CertificateOrChain(Message m, Properties props) {
+        X509Certificate[] chain = loadX509CertificateOrChain(m, props);
+        return encodeX509CertificateChain(chain);
+    }
+    public static X509Certificate[] loadX509CertificateOrChain(Message m, Properties props) {
+        KeyStore keyStore = KeyManagementUtils.loadPersistKeyStore(m, props);
+        String alias = props.getProperty(RSSEC_KEY_STORE_ALIAS);
+        return loadX509CertificateOrChain(keyStore, alias);
+    }
+    private static X509Certificate[] loadX509CertificateOrChain(KeyStore keyStore, String alias) {
+        try {
+            Certificate[] certs = keyStore.getCertificateChain(alias);
+            if (certs != null) {
+                return Arrays.copyOf(certs, certs.length, X509Certificate[].class);
+            } else {
+                return new X509Certificate[]{(X509Certificate)CryptoUtils.loadCertificate(keyStore, alias)};
+            }
+        } catch (Exception ex) {
+            throw new SecurityException(ex);
+        }    
+    }
     
     public static PublicKey loadPublicKey(Message m, Properties props) {
         KeyStore keyStore = KeyManagementUtils.loadPersistKeyStore(m, props);
@@ -89,13 +115,14 @@ public final class KeyManagementUtils {
                                             Properties props, 
                                             Bus bus, 
                                             PrivateKeyPasswordProvider provider,
-                                            String keyOper) {
+                                            String keyOper,
+                                            String alias) {
         
         String keyPswd = props.getProperty(RSSEC_KEY_PSWD);
-        String alias = getKeyId(m, props, RSSEC_KEY_STORE_ALIAS, keyOper);
+        String theAlias = alias != null ? alias : getKeyId(m, props, RSSEC_KEY_STORE_ALIAS, keyOper);
         char[] keyPswdChars = provider != null ? provider.getPassword(props) 
             : keyPswd != null ? keyPswd.toCharArray() : null;    
-        return CryptoUtils.loadPrivateKey(keyStore, keyPswdChars, alias);
+        return CryptoUtils.loadPrivateKey(keyStore, keyPswdChars, theAlias);
     }
     
     public static PrivateKey loadPrivateKey(Message m, String keyStoreLocProp, String keyOper) {
@@ -148,9 +175,13 @@ public final class KeyManagementUtils {
         return cb;
     }
     
-    public static PrivateKey loadPrivateKey(Message m, Properties props, String keyOper) {
-        Bus bus = m.getExchange().getBus();
+    public static RSAPrivateKey loadPrivateKey(Message m, Properties props, String keyOper) {
         KeyStore keyStore = loadPersistKeyStore(m, props);
+        return (RSAPrivateKey)loadPrivateKey(keyStore, m, props, keyOper, null);
+    }
+    private static RSAPrivateKey loadPrivateKey(KeyStore keyStore, Message m, Properties props, String keyOper, 
+                                                String alias) {
+        Bus bus = m.getExchange().getBus();
         PrivateKeyPasswordProvider cb = loadPasswordProvider(m, props, keyOper);
         if (cb != null && m.getExchange().getInMessage() != null) {
             SecurityContext sc = m.getExchange().getInMessage().get(SecurityContext.class);
@@ -161,7 +192,7 @@ public final class KeyManagementUtils {
                 }
             }
         }
-        return loadPrivateKey(keyStore, m, props, bus, cb, keyOper);
+        return (RSAPrivateKey)loadPrivateKey(keyStore, m, props, bus, cb, keyOper, alias);
     }
     public static KeyStore loadPersistKeyStore(Message m, Properties props) {
         KeyStore keyStore = (KeyStore)m.getExchange().get(props.get(RSSEC_KEY_STORE_FILE));
@@ -182,7 +213,9 @@ public final class KeyManagementUtils {
             throw new SecurityException(ex);
         }
     }
-
+    public static List<String> encodeX509CertificateChain(X509Certificate[] chain) {
+        return encodeX509CertificateChain(Arrays.asList(chain));
+    }
     public static List<String> encodeX509CertificateChain(List<X509Certificate> chain) {
         List<String> encodedChain = new ArrayList<String>(chain.size());
         for (X509Certificate cert : chain) {
@@ -252,4 +285,22 @@ public final class KeyManagementUtils {
         }
         return props; 
     }
+    public static RSAPrivateKey loadPrivateKey(Message m, Properties props, 
+                                               List<X509Certificate> inCert, String keyOper) {
+        KeyStore keyStore = loadPersistKeyStore(m, props);
+        try {
+            Object[] inCertArray = inCert.toArray();
+            // perhaps inCert properties can be optionally used as aliases
+            for (Enumeration<String> e = keyStore.aliases(); e.hasMoreElements();) {
+                String alias = e.nextElement();
+                X509Certificate[] chain = loadX509CertificateOrChain(keyStore, alias);
+                if (chain != null && Arrays.equals(chain, inCertArray)) {
+                    return loadPrivateKey(keyStore, m, props, keyOper, alias);
+                }
+            }
+        } catch (Exception ex) {
+            throw new SecurityException(ex);
+        }
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/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 62ecbb0..ae820f6 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
@@ -19,12 +19,14 @@
 package org.apache.cxf.rs.security.jose.jwe;
 
 import java.nio.ByteBuffer;
+import java.security.cert.X509Certificate;
 import java.security.interfaces.ECPrivateKey;
 import java.security.interfaces.ECPublicKey;
 import java.security.interfaces.RSAPrivateKey;
 import java.security.interfaces.RSAPublicKey;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 import java.util.Properties;
 
 import javax.crypto.KeyAgreement;
@@ -34,6 +36,7 @@ import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.common.util.crypto.MessageDigestUtils;
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 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.JoseHeaders;
 import org.apache.cxf.rs.security.jose.JoseUtils;
@@ -49,6 +52,7 @@ public final class JweUtils {
     private static final String RSSEC_ENCRYPTION_OUT_PROPS = "rs.security.encryption.out.properties";
     private static final String RSSEC_ENCRYPTION_IN_PROPS = "rs.security.encryption.in.properties";
     private static final String RSSEC_ENCRYPTION_PROPS = "rs.security.encryption.properties";
+    private static final String RSSEC_ENCRYPTION_REPORT_KEY_PROP = "rs.security.jwe.report.public.key";
     
     private JweUtils() {
         
@@ -221,16 +225,21 @@ public final class JweUtils {
                                           getContentDecryptionAlgorithm(key.getAlgorithm()));
     }
     public static JweEncryptionProvider loadEncryptionProvider(boolean required) {
-        return loadEncryptionProvider(JAXRSUtils.getCurrentMessage(), required);
+        return loadEncryptionProvider(null, required);
     }
-    public static JweEncryptionProvider loadEncryptionProvider(Message m, boolean required) {
-        
+    public static JweEncryptionProvider loadEncryptionProvider(JweHeaders headers, boolean required) {
+        Message m = JAXRSUtils.getCurrentMessage();        
         Properties props = KeyManagementUtils.loadStoreProperties(m, required, 
                                                                   RSSEC_ENCRYPTION_OUT_PROPS, RSSEC_ENCRYPTION_PROPS);
         if (props == null) {
             return null;
         }
         
+        boolean reportPublicKey = 
+            headers != null && MessageUtils.isTrue(
+                MessageUtils.getContextualProperty(m, RSSEC_ENCRYPTION_REPORT_KEY_PROP, 
+                                                   KeyManagementUtils.RSSEC_REPORT_KEY_PROP));
+        
         KeyEncryptionAlgorithm keyEncryptionProvider = null;
         String keyEncryptionAlgo = getKeyEncryptionAlgo(m, props, null, null);
         String contentEncryptionAlgo = getContentEncryptionAlgo(m, props, null);
@@ -244,11 +253,18 @@ public final class JweUtils {
                 ctEncryptionProvider = getContentEncryptionAlgorithm(jwk, contentEncryptionAlgo);
             } else {
                 keyEncryptionProvider = getKeyEncryptionAlgorithm(jwk, keyEncryptionAlgo);
+                if (reportPublicKey) {
+                    JwkUtils.setPublicKeyInfo(jwk, headers, keyEncryptionAlgo);
+                }
             }
         } else {
             keyEncryptionProvider = getRSAKeyEncryptionAlgorithm(
                 (RSAPublicKey)KeyManagementUtils.loadPublicKey(m, props), 
                 keyEncryptionAlgo);
+            if (reportPublicKey) {
+                headers.setX509Chain(KeyManagementUtils.loadAndEncodeX509CertificateOrChain(m, props));
+            }
+            
         }
         return createJweEncryptionProvider(keyEncryptionProvider, 
                                     ctEncryptionProvider, 
@@ -256,32 +272,45 @@ public final class JweUtils {
                                     props.getProperty(JSON_WEB_ENCRYPTION_ZIP_ALGO_PROP));
     }
     public static JweDecryptionProvider loadDecryptionProvider(boolean required) {
-        return loadDecryptionProvider(JAXRSUtils.getCurrentMessage(), required);
+        return loadDecryptionProvider(null, required);
     }
-    public static JweDecryptionProvider loadDecryptionProvider(Message m, boolean required) {
+    public static JweDecryptionProvider loadDecryptionProvider(JweHeaders inHeaders, boolean required) {
+        Message m = JAXRSUtils.getCurrentMessage();
         Properties props = KeyManagementUtils.loadStoreProperties(m, required, 
                                                                   RSSEC_ENCRYPTION_IN_PROPS, RSSEC_ENCRYPTION_PROPS);
         if (props == null) {
             return null;
         }    
+        
         KeyDecryptionAlgorithm keyDecryptionProvider = null;
         String contentEncryptionAlgo = getContentEncryptionAlgo(m, props, null);
         SecretKey ctDecryptionKey = null;
         String keyEncryptionAlgo = getKeyEncryptionAlgo(m, props, null, null);
-        if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
-            JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_DECRYPT);
-            keyEncryptionAlgo = getKeyEncryptionAlgo(m, props, jwk.getAlgorithm(),
-                                                     getDefaultKeyAlgo(jwk));
-            if ("direct".equals(keyEncryptionAlgo)) {
-                contentEncryptionAlgo = getContentEncryptionAlgo(m, props, contentEncryptionAlgo);
-                ctDecryptionKey = getContentDecryptionSecretKey(jwk, contentEncryptionAlgo);
+        if (inHeaders != null && inHeaders.getHeader(JoseConstants.HEADER_X509_CHAIN) != null) {
+            //TODO: validate incoming public keys or certificates  
+            //TODO: optionally validate inHeaders.getAlgorithm against a property in props
+            // Supporting loading a private key via a certificate for now
+            List<X509Certificate> chain = KeyManagementUtils.toX509CertificateChain(inHeaders.getX509Chain());
+            RSAPrivateKey privateKey = 
+                KeyManagementUtils.loadPrivateKey(m, props, chain, JsonWebKey.KEY_OPER_DECRYPT);
+            contentEncryptionAlgo = inHeaders.getContentEncryptionAlgorithm();
+            keyDecryptionProvider = getRSAKeyDecryptionAlgorithm(privateKey, inHeaders.getKeyEncryptionAlgorithm());
+        } else {
+            if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
+                JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_DECRYPT);
+                keyEncryptionAlgo = getKeyEncryptionAlgo(m, props, jwk.getAlgorithm(),
+                                                         getDefaultKeyAlgo(jwk));
+                if ("direct".equals(keyEncryptionAlgo)) {
+                    contentEncryptionAlgo = getContentEncryptionAlgo(m, props, contentEncryptionAlgo);
+                    ctDecryptionKey = getContentDecryptionSecretKey(jwk, contentEncryptionAlgo);
+                } else {
+                    keyDecryptionProvider = getKeyDecryptionAlgorithm(jwk, keyEncryptionAlgo);
+                }
             } else {
-                keyDecryptionProvider = getKeyDecryptionAlgorithm(jwk, keyEncryptionAlgo);
+                keyDecryptionProvider = getRSAKeyDecryptionAlgorithm(
+                    (RSAPrivateKey)KeyManagementUtils.loadPrivateKey(
+                        m, props, JsonWebKey.KEY_OPER_DECRYPT), keyEncryptionAlgo);
             }
-        } else {
-            keyDecryptionProvider = getRSAKeyDecryptionAlgorithm(
-                (RSAPrivateKey)KeyManagementUtils.loadPrivateKey(
-                    m, props, JsonWebKey.KEY_OPER_DECRYPT), keyEncryptionAlgo);
         }
         return createJweDecryptionProvider(keyDecryptionProvider, ctDecryptionKey, contentEncryptionAlgo);
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/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 2f6cf77..911ddda 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
@@ -38,10 +38,12 @@ import org.apache.cxf.Bus;
 import org.apache.cxf.common.util.Base64UrlUtility;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.common.util.crypto.CryptoUtils;
+import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.jaxrs.utils.ResourceUtils;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.rs.security.jose.JoseConstants;
+import org.apache.cxf.rs.security.jose.JoseHeaders;
 import org.apache.cxf.rs.security.jose.JoseUtils;
 import org.apache.cxf.rs.security.jose.jaxrs.KeyManagementUtils;
 import org.apache.cxf.rs.security.jose.jaxrs.PrivateKeyPasswordProvider;
@@ -438,4 +440,15 @@ public final class JwkUtils {
     private static JweHeaders toJweHeaders(String ct) {
         return new JweHeaders(Collections.<String, Object>singletonMap(JoseConstants.HEADER_CONTENT_TYPE, ct));
     }
+    public static void setPublicKeyInfo(JsonWebKey jwk, JoseHeaders headers, String algo) {
+        if (JsonWebKey.KEY_TYPE_RSA.equals(jwk.getKeyType())) {
+            List<String> chain = CastUtils.cast((List<?>)jwk.getProperty("x5c"));
+            if (chain != null) {
+                headers.setX509Chain(chain);
+            } else {
+                headers.setJsonWebKey(
+                    JwkUtils.fromRSAPublicKey(JwkUtils.toRSAPublicKey(jwk), algo));
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/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 53ac53e..1e8e6d4 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
@@ -18,6 +18,7 @@
  */
 package org.apache.cxf.rs.security.jose.jws;
 
+import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPrivateKey;
 import java.security.interfaces.RSAPublicKey;
 import java.util.ArrayList;
@@ -31,6 +32,7 @@ import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 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.JoseHeaders;
 import org.apache.cxf.rs.security.jose.JoseUtils;
@@ -44,6 +46,7 @@ public final class JwsUtils {
     private static final String RSSEC_SIGNATURE_OUT_PROPS = "rs.security.signature.out.properties";
     private static final String RSSEC_SIGNATURE_IN_PROPS = "rs.security.signature.in.properties";
     private static final String RSSEC_SIGNATURE_PROPS = "rs.security.signature.properties";
+    private static final String JSON_WEB_SIGNATURE_REPORT_KEY_PROP = "rs.security.jws.report.public.key";
     private JwsUtils() {
         
     }
@@ -132,22 +135,36 @@ public final class JwsUtils {
         return map;
     }
     public static JwsSignatureProvider loadSignatureProvider(boolean required) {
-        return loadSignatureProvider(JAXRSUtils.getCurrentMessage(), required);
+        return loadSignatureProvider(null, required);    
     }
-    public static JwsSignatureProvider loadSignatureProvider(Message m, boolean required) {
+    public static JwsSignatureProvider loadSignatureProvider(JoseHeaders headers, boolean required) {
+        Message m = JAXRSUtils.getCurrentMessage();
         Properties props = KeyManagementUtils.loadStoreProperties(m, required, 
                                                                   RSSEC_SIGNATURE_OUT_PROPS, RSSEC_SIGNATURE_PROPS);
         if (props == null) {
             return null;
         }
-        return loadSignatureProvider(m, props, false);
+        JwsSignatureProvider theSigProvider = loadSignatureProvider(m, props, headers, false);
+        if (headers != null) {
+            headers.setAlgorithm(theSigProvider.getAlgorithm());
+        }
+        return theSigProvider;
     }
     public static JwsSignatureVerifier loadSignatureVerifier(boolean required) {
-        return loadSignatureVerifier(JAXRSUtils.getCurrentMessage(), required);
+        return loadSignatureVerifier(null, required);
+    }
+    public static JwsSignatureVerifier loadSignatureVerifier(JoseHeaders headers, boolean required) {
+        Message m = JAXRSUtils.getCurrentMessage();
+        Properties props = KeyManagementUtils.loadStoreProperties(m, required, 
+                                                                  RSSEC_SIGNATURE_IN_PROPS, RSSEC_SIGNATURE_PROPS);
+        if (props == null) {
+            return null;
+        }
+        return loadSignatureVerifier(m, props, headers, false);
     }
     public static List<JwsSignatureProvider> loadSignatureProviders(String propLoc, Message m) {
         Properties props = loadProperties(m, propLoc);
-        JwsSignatureProvider theSigProvider = loadSignatureProvider(m, props, true);
+        JwsSignatureProvider theSigProvider = loadSignatureProvider(m, props, null, true);
         if (theSigProvider != null) {
             return Collections.singletonList(theSigProvider);
         }
@@ -166,18 +183,10 @@ public final class JwsUtils {
         }
         return theSigProviders;
     }
-    public static JwsSignatureVerifier loadSignatureVerifier(Message m, boolean required) {
-        Properties props = KeyManagementUtils.loadStoreProperties(m, required, 
-                                                                  RSSEC_SIGNATURE_IN_PROPS, RSSEC_SIGNATURE_PROPS);
-        if (props == null) {
-            return null;
-        }
-        return loadSignatureVerifier(m, props, false);
-    }
     
     public static List<JwsSignatureVerifier> loadSignatureVerifiers(String propLoc, Message m) {
         Properties props = loadProperties(m, propLoc);
-        JwsSignatureVerifier theVerifier = loadSignatureVerifier(m, props, true);
+        JwsSignatureVerifier theVerifier = loadSignatureVerifier(m, props, null, true);
         if (theVerifier != null) {
             return Collections.singletonList(theVerifier);
         }
@@ -200,30 +209,56 @@ public final class JwsUtils {
         //TODO: validate JWS specific constraints
         return JoseUtils.validateCriticalHeaders(headers);
     }
-    private static JwsSignatureProvider loadSignatureProvider(Message m, Properties props, 
+    private static JwsSignatureProvider loadSignatureProvider(Message m, 
+                                                              Properties props,
+                                                              JoseHeaders headers,
                                                               boolean ignoreNullProvider) {
         JwsSignatureProvider theSigProvider = null; 
         String rsaSignatureAlgo = null;
+        boolean reportPublicKey = 
+            headers != null && MessageUtils.isTrue(
+                MessageUtils.getContextualProperty(m, JSON_WEB_SIGNATURE_REPORT_KEY_PROP,
+                                                   KeyManagementUtils.RSSEC_REPORT_KEY_PROP)); 
         if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
             JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_SIGN);
             if (jwk != null) {
                 rsaSignatureAlgo = getSignatureAlgo(m, props, jwk.getAlgorithm(), getDefaultKeyAlgo(jwk));
                 theSigProvider = JwsUtils.getSignatureProvider(jwk, rsaSignatureAlgo);
+                if (reportPublicKey) {
+                    JwkUtils.setPublicKeyInfo(jwk, headers, rsaSignatureAlgo);
+                }
             }
         } else {
             rsaSignatureAlgo = getSignatureAlgo(m, props, null, null);
             RSAPrivateKey pk = (RSAPrivateKey)KeyManagementUtils.loadPrivateKey(m, props, 
                 JsonWebKey.KEY_OPER_SIGN);
             theSigProvider = getRSAKeySignatureProvider(pk, rsaSignatureAlgo);
+            if (reportPublicKey) {
+                headers.setX509Chain(KeyManagementUtils.loadAndEncodeX509CertificateOrChain(m, props));
+            }
         }
         if (theSigProvider == null && !ignoreNullProvider) {
             throw new SecurityException();
         }
         return theSigProvider;
     }
-    private static JwsSignatureVerifier loadSignatureVerifier(Message m, Properties props, 
+    private static JwsSignatureVerifier loadSignatureVerifier(Message m, 
+                                                              Properties props,
+                                                              JoseHeaders inHeaders, 
                                                               boolean ignoreNullVerifier) {
         JwsSignatureVerifier theVerifier = null;
+        if (inHeaders != null) {
+            //TODO: validate incoming public keys or certificates  
+            //TODO: optionally validate inHeaders.getAlgorithm against a property in props
+            if (inHeaders.getHeader(JoseConstants.HEADER_JSON_WEB_KEY) != null) {
+                JsonWebKey publicJwk = inHeaders.getJsonWebKey();
+                return getSignatureVerifier(publicJwk, inHeaders.getAlgorithm());
+            } else if (inHeaders.getHeader(JoseConstants.HEADER_X509_CHAIN) != null) {
+                List<X509Certificate> chain = KeyManagementUtils.toX509CertificateChain(inHeaders.getX509Chain());
+                return getRSAKeySignatureVerifier((RSAPublicKey)chain.get(0).getPublicKey(), inHeaders.getAlgorithm());
+            }
+        }
+        
         String rsaSignatureAlgo = null;
         if (JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE))) {
             JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, JsonWebKey.KEY_OPER_VERIFY);

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/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 cd113ae..ba1c033 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
@@ -220,6 +220,14 @@ public class JAXRSJweJwsTest extends AbstractBusClientServerTestBase {
         assertEquals("book", text);
     }
     @Test
+    public void testJweRsaJwsRsaCertInHeaders() throws Exception {
+        String address = "https://localhost:" + PORT + "/jwejwsrsaCertInHeaders";
+        BookStore bs = createJweJwsBookStore(address, null, null);
+        WebClient.getConfig(bs).getRequestContext().put("rs.security.report.public.key", "true");
+        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/5e919271/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 ce9a491..155cf69 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
@@ -114,6 +114,25 @@ under the License.
             <entry key="rs.security.default.algorithms" value="true"/>
         </jaxrs:properties>
     </jaxrs:server>
+    <jaxrs:server address="https://localhost:${testutil.ports.jaxrs-jwt}/jwejwsrsaCertInHeaders">
+        <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.storeonly.properties"/>
+            <entry key="rs.security.signature.in.properties" value="org/apache/cxf/systest/jaxrs/security/bob.rs.storeonly.properties"/>
+            <entry key="rs.security.encryption.out.properties" value="org/apache/cxf/systest/jaxrs/security/bob.rs.properties"/>
+            <entry key="rs.security.signature.out.properties" value="org/apache/cxf/systest/jaxrs/security/alice.rs.properties"/>
+            <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/5e919271/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.rs.storeonly.properties
----------------------------------------------------------------------
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.rs.storeonly.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.rs.storeonly.properties
new file mode 100644
index 0000000..3dd7174
--- /dev/null
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/alice.rs.storeonly.properties
@@ -0,0 +1,19 @@
+#    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=jks
+rs.security.keystore.password=password
+rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/alice.jks

http://git-wip-us.apache.org/repos/asf/cxf/blob/5e919271/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.storeonly.properties
----------------------------------------------------------------------
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.storeonly.properties b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.storeonly.properties
new file mode 100644
index 0000000..9f69a3d
--- /dev/null
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/bob.rs.storeonly.properties
@@ -0,0 +1,21 @@
+#
+#    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=jks
+rs.security.keystore.password=password
+rs.security.keystore.file=org/apache/cxf/systest/jaxrs/security/certs/bob.jks