[CXF-6972] Support for per-recipient JWE JSON headers
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/bf3b463d Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/bf3b463d Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/bf3b463d Branch: refs/heads/master-jaxrs-2.1 Commit: bf3b463d2b5e16ce69e4ca862d3ca141a750fa15 Parents: 2d38ac0 Author: Sergey Beryozkin <sberyoz...@gmail.com> Authored: Tue Jul 19 14:46:10 2016 +0300 Committer: Sergey Beryozkin <sberyoz...@gmail.com> Committed: Tue Jul 19 14:46:10 2016 +0300 ---------------------------------------------------------------------- .../cxf/rs/security/jose/jwe/JweHeaders.java | 4 +++ .../rs/security/jose/jwe/JweJsonConsumer.java | 6 +++- .../rs/security/jose/jwe/JweJsonProducer.java | 2 +- .../cxf/rs/security/jose/jws/JwsHeaders.java | 4 +++ .../security/jose/jwe/JweJsonConsumerTest.java | 29 ++++++++++++++++++++ .../security/jose/jwe/JweJsonProducerTest.java | 14 +++++++--- 6 files changed, 53 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/bf3b463d/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java index d1d8651..34266f6 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java @@ -19,6 +19,7 @@ package org.apache.cxf.rs.security.jose.jwe; +import java.util.Collections; import java.util.Map; import org.apache.cxf.common.util.Base64UrlUtility; @@ -48,6 +49,9 @@ public class JweHeaders extends JoseHeaders { public JweHeaders(Map<String, Object> values) { super(values); } + public JweHeaders(String kid) { + this(Collections.singletonMap(JoseConstants.HEADER_KEY_ID, kid)); + } public JweHeaders(KeyAlgorithm keyEncAlgo, ContentAlgorithm ctEncAlgo) { this(keyEncAlgo, ctEncAlgo, false); } http://git-wip-us.apache.org/repos/asf/cxf/blob/bf3b463d/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumer.java index 0c8aecd..6e3954b 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumer.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumer.java @@ -52,7 +52,11 @@ public class JweJsonConsumer { } public JweDecryptionOutput decryptWith(JweDecryptionProvider jwe) { - JweJsonEncryptionEntry entry = getJweDecryptionEntry(jwe); + return decryptWith(jwe, (Map<String, Object>)null); + } + public JweDecryptionOutput decryptWith(JweDecryptionProvider jwe, + Map<String, Object> recipientProps) { + JweJsonEncryptionEntry entry = getJweDecryptionEntry(jwe, recipientProps); return decryptWith(jwe, entry); } public JweDecryptionOutput decryptWith(JweDecryptionProvider jwe, JweJsonEncryptionEntry entry) { http://git-wip-us.apache.org/repos/asf/cxf/blob/bf3b463d/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducer.java index 3c8385d..3a3d745 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducer.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducer.java @@ -113,7 +113,7 @@ public class JweJsonProducer { LOG.warning("union and recipient unprotected headers have duplicate values"); throw new JweException(JweException.Error.INVALID_JSON_JWE); } - jsonHeaders = new JweHeaders(unionHeaders.asMap()); + jsonHeaders = new JweHeaders(new LinkedHashMap<String, Object>(unionHeaders.asMap())); jsonHeaders.asMap().putAll(perRecipientUnprotected.asMap()); } else { jsonHeaders = unionHeaders; http://git-wip-us.apache.org/repos/asf/cxf/blob/bf3b463d/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsHeaders.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsHeaders.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsHeaders.java index e860311..322c95b 100644 --- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsHeaders.java +++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsHeaders.java @@ -18,6 +18,7 @@ */ package org.apache.cxf.rs.security.jose.jws; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -42,6 +43,9 @@ public class JwsHeaders extends JoseHeaders { public JwsHeaders(Map<String, Object> values) { super(values); } + public JwsHeaders(String kid) { + this(Collections.singletonMap(JoseConstants.HEADER_KEY_ID, kid)); + } public JwsHeaders(SignatureAlgorithm sigAlgo) { init(sigAlgo); } http://git-wip-us.apache.org/repos/asf/cxf/blob/bf3b463d/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumerTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumerTest.java b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumerTest.java index c5d7d58..38c610d 100644 --- a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumerTest.java +++ b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JweJsonConsumerTest.java @@ -19,6 +19,7 @@ package org.apache.cxf.rs.security.jose.jwe; import java.security.Security; +import java.util.Collections; import javax.crypto.Cipher; import javax.crypto.SecretKey; @@ -127,6 +128,34 @@ public class JweJsonConsumerTest extends Assert { assertEquals(text, out.getContentText()); assertEquals(JweJsonProducerTest.EXTRA_AAD_SOURCE, consumer.getAadText()); } + + @Test + public void testMultipleRecipients() { + final String text = "The true sign of intelligence is not knowledge but imagination."; + + SecretKey wrapperKey1 = CryptoUtils.createSecretKeySpec(JweJsonProducerTest.WRAPPER_BYTES1, + "AES"); + SecretKey wrapperKey2 = CryptoUtils.createSecretKeySpec(JweJsonProducerTest.WRAPPER_BYTES2, + "AES"); + JweJsonConsumer consumer = new JweJsonConsumer(JweJsonProducerTest.MULTIPLE_RECIPIENTS_OUTPUT); + KeyAlgorithm keyAlgo = consumer.getSharedUnprotectedHeader().getKeyEncryptionAlgorithm(); + ContentAlgorithm ctAlgo = consumer.getProtectedHeader().getContentEncryptionAlgorithm(); + // Recipient 1 + JweDecryptionProvider jwe1 = JweUtils.createJweDecryptionProvider(wrapperKey1, keyAlgo, ctAlgo); + JweDecryptionOutput out1 = consumer.decryptWith(jwe1, + Collections.singletonMap("kid", "key1")); + assertEquals(text, out1.getContentText()); + // Recipient 2 + JweDecryptionProvider jwe2 = JweUtils.createJweDecryptionProvider(wrapperKey2, keyAlgo, ctAlgo); + + JweDecryptionOutput out2 = consumer.decryptWith(jwe2, + Collections.singletonMap("kid", "key2")); + assertEquals(text, out2.getContentText()); + + // Extra AAD + assertEquals(JweJsonProducerTest.EXTRA_AAD_SOURCE, consumer.getAadText()); + } + @Test public void testSingleRecipientAllTypeOfHeadersAndAadModified() { SecretKey wrapperKey = CryptoUtils.createSecretKeySpec(JweJsonProducerTest.WRAPPER_BYTES1, http://git-wip-us.apache.org/repos/asf/cxf/blob/bf3b463d/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducerTest.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducerTest.java b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducerTest.java index fb3785d..b6db1c3 100644 --- a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducerTest.java +++ b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwe/JweJsonProducerTest.java @@ -102,9 +102,11 @@ public class JweJsonProducerTest extends Assert { + "\"recipients\":" + "[" + "{" + + "\"header\":{\"kid\":\"key1\"}," + "\"encrypted_key\":\"b3-M9_CRgT3wEBhhXlpb-BoY7vtA4W_N\"" + "}," + "{" + + "\"header\":{\"kid\":\"key2\"}," + "\"encrypted_key\":\"6a_nnEYO45qB_Vp6N2QbFQ7Cv1uecbiE\"" + "}" + "]," @@ -277,7 +279,7 @@ public class JweJsonProducerTest extends Assert { sharedUnprotectedHeaders.setJsonWebKeysUrl("https://server.example.com/keys.jwks"); sharedUnprotectedHeaders.setKeyEncryptionAlgorithm(KeyAlgorithm.A128KW); - List<JweEncryptionProvider> jweList = new LinkedList<JweEncryptionProvider>(); + List<JweEncryptionProvider> jweProviders = new LinkedList<JweEncryptionProvider>(); KeyEncryptionProvider keyEncryption1 = JweUtils.getSecretKeyEncryptionAlgorithm(wrapperKey1, KeyAlgorithm.A128KW); @@ -287,8 +289,12 @@ public class JweJsonProducerTest extends Assert { KeyEncryptionProvider keyEncryption2 = JweUtils.getSecretKeyEncryptionAlgorithm(wrapperKey2, KeyAlgorithm.A128KW); JweEncryptionProvider jwe2 = new JweEncryption(keyEncryption2, contentEncryption); - jweList.add(jwe1); - jweList.add(jwe2); + jweProviders.add(jwe1); + jweProviders.add(jwe2); + + List<JweHeaders> perRecipientHeades = new LinkedList<JweHeaders>(); + perRecipientHeades.add(new JweHeaders("key1")); + perRecipientHeades.add(new JweHeaders("key2")); JweJsonProducer p = new JweJsonProducer(protectedHeaders, sharedUnprotectedHeaders, @@ -303,7 +309,7 @@ public class JweJsonProducerTest extends Assert { } }; - String jweJson = p.encryptWith(jweList); + String jweJson = p.encryptWith(jweProviders, perRecipientHeades); assertEquals(MULTIPLE_RECIPIENTS_OUTPUT, jweJson); } }