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