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/01/15 23:45:03 UTC
cxf git commit: Changes to JwsJson to support flattened and detached
mode for Daniel's work
Repository: cxf
Updated Branches:
refs/heads/master bdcc48de5 -> 85ebf3f70
Changes to JwsJson to support flattened and detached mode for Daniel's work
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/85ebf3f7
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/85ebf3f7
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/85ebf3f7
Branch: refs/heads/master
Commit: 85ebf3f701d6c2127c7ec761638cafc6c086fc1c
Parents: bdcc48d
Author: Sergey Beryozkin <sb...@talend.com>
Authored: Thu Jan 15 22:44:44 2015 +0000
Committer: Sergey Beryozkin <sb...@talend.com>
Committed: Thu Jan 15 22:44:44 2015 +0000
----------------------------------------------------------------------
.../rs/security/jose/jws/JwsJsonConsumer.java | 55 +++++++++++++-------
.../rs/security/jose/jws/JwsJsonProducer.java | 51 +++++++++++-------
.../jose/jws/JwsJsonSignatureEntry.java | 11 +++-
.../security/jose/jws/JwsJsonProducerTest.java | 18 +++++++
4 files changed, 94 insertions(+), 41 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/85ebf3f7/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java
index 90fe02a..c1690d8 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonConsumer.java
@@ -19,7 +19,6 @@
package org.apache.cxf.rs.security.jose.jws;
import java.security.interfaces.RSAPublicKey;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -38,44 +37,58 @@ public class JwsJsonConsumer {
private String jwsSignedDocument;
private String encodedJwsPayload;
- private List<JwsJsonSignatureEntry> signatureEntries;
+ private List<JwsJsonSignatureEntry> signatureEntries = new LinkedList<JwsJsonSignatureEntry>();
/**
* @param jwsSignedDocument
* signed JWS Document
*/
public JwsJsonConsumer(String jwsSignedDocument) {
+ this(jwsSignedDocument, null);
+ }
+ public JwsJsonConsumer(String jwsSignedDocument, String encodedDetachedPayload) {
this.jwsSignedDocument = jwsSignedDocument;
- prepare();
+ prepare(encodedDetachedPayload);
}
- private void prepare() {
+ private void prepare(String encodedDetachedPayload) {
JsonMapObject jsonObject = new JsonMapObject();
new JsonMapObjectReaderWriter().fromJson(jsonObject, jwsSignedDocument);
- encodedJwsPayload = (String)jsonObject.asMap().get("payload");
+
+ Map<String, Object> jsonObjectMap = jsonObject.asMap();
+ encodedJwsPayload = (String)jsonObjectMap.get("payload");
+ if (encodedJwsPayload == null) {
+ encodedJwsPayload = encodedDetachedPayload;
+ }
if (encodedJwsPayload == null) {
throw new SecurityException("Invalid JWS JSON sequence: no payload is available");
}
- List<Map<String, Object>> signatureArray = CastUtils.cast((List<?>)jsonObject.asMap().get("signatures"));
-
- this.signatureEntries = new ArrayList<JwsJsonSignatureEntry>(signatureArray.size());
-
- for (Map<String, Object> signatureEntry : signatureArray) {
- String protectedHeader = (String)signatureEntry.get("protected");
- Map<String, Object> header = CastUtils.cast((Map<?, ?>)signatureEntry.get("header"));
- String signature = (String)signatureEntry.get("signature");
- JwsJsonSignatureEntry signatureObject =
- new JwsJsonSignatureEntry(encodedJwsPayload,
- protectedHeader,
- signature,
- header != null ? new JwsJsonUnprotectedHeader(header) : null);
- this.signatureEntries.add(signatureObject);
+ List<Map<String, Object>> signatureArray = CastUtils.cast((List<?>)jsonObjectMap.get("signatures"));
+ if (signatureArray != null) {
+ if (jsonObjectMap.containsKey("signature")) {
+ throw new SecurityException("Invalid JWS JSON sequence");
+ }
+ for (Map<String, Object> signatureEntry : signatureArray) {
+ this.signatureEntries.add(getSignatureObject(signatureEntry));
+ }
+ } else {
+ this.signatureEntries.add(getSignatureObject(jsonObjectMap));
}
if (signatureEntries.isEmpty()) {
throw new SecurityException("Invalid JWS JSON sequence: no signatures are available");
}
}
+ protected JwsJsonSignatureEntry getSignatureObject(Map<String, Object> signatureEntry) {
+ String protectedHeader = (String)signatureEntry.get("protected");
+ Map<String, Object> header = CastUtils.cast((Map<?, ?>)signatureEntry.get("header"));
+ String signature = (String)signatureEntry.get("signature");
+ return
+ new JwsJsonSignatureEntry(encodedJwsPayload,
+ protectedHeader,
+ signature,
+ header != null ? new JwsJsonUnprotectedHeader(header) : null);
+ }
public String getSignedDocument() {
return this.jwsSignedDocument;
}
@@ -159,6 +172,8 @@ public class JwsJsonConsumer {
return verifySignatureWith(JwsUtils.getSignatureVerifier(key));
}
public JwsJsonProducer toProducer() {
- return new JwsJsonProducer(getDecodedJwsPayload(), signatureEntries);
+ JwsJsonProducer p = new JwsJsonProducer(getDecodedJwsPayload());
+ p.getSignatureEntries().addAll(signatureEntries);
+ return p;
}
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/85ebf3f7/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java
index c9c2387..2d11072 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java
@@ -30,37 +30,58 @@ import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.rs.security.jose.JoseHeaders;
import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
public class JwsJsonProducer {
+ private boolean supportFlattened;
private String plainPayload;
private String encodedPayload;
- private StringBuilder jwsJsonSignedDocBuilder = new StringBuilder();
private List<JwsJsonSignatureEntry> signatures = new LinkedList<JwsJsonSignatureEntry>();
public JwsJsonProducer(String tbsDocument) {
+ this(tbsDocument, false);
+ }
+ public JwsJsonProducer(String tbsDocument, boolean supportFlattened) {
+ this.supportFlattened = supportFlattened;
this.plainPayload = tbsDocument;
this.encodedPayload = Base64UrlUtility.encode(tbsDocument);
}
- public JwsJsonProducer(String tbsDocument, List<JwsJsonSignatureEntry> signatures) {
- this(tbsDocument);
- for (JwsJsonSignatureEntry entry : signatures) {
- updateJwsJsonSignedDocument(entry);
- }
- }
-
+
public String getPlainPayload() {
return plainPayload;
}
public String getUnsignedEncodedPayload() {
return encodedPayload;
}
-
public String getJwsJsonSignedDocument() {
+ return getJwsJsonSignedDocument(false);
+ }
+ public String getJwsJsonSignedDocument(boolean detached) {
if (signatures.isEmpty()) {
throw new SecurityException("Signature is not available");
}
- return jwsJsonSignedDocBuilder.toString() + "]}";
+ StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ if (!detached) {
+ sb.append("\"payload\":\"" + encodedPayload + "\"");
+ sb.append(",");
+ }
+ if (!supportFlattened || signatures.size() > 1) {
+ sb.append("\"signatures\":[");
+ for (int i = 0; i < signatures.size(); i++) {
+ JwsJsonSignatureEntry signature = signatures.get(i);
+ if (i > 0) {
+ sb.append(",");
+ }
+ sb.append(signature.toJson());
+ }
+ sb.append("]");
+ } else {
+ sb.append(signatures.get(0).toJson(true));
+ }
+ sb.append("}");
+ return sb.toString();
}
public List<JwsJsonSignatureEntry> getSignatureEntries() {
- return Collections.unmodifiableList(signatures);
+ return signatures;
}
+
public MultivaluedMap<String, JwsJsonSignatureEntry> getSignatureEntryMap() {
return JwsUtils.getJwsJsonSignatureMap(signatures);
}
@@ -122,15 +143,7 @@ public class JwsJsonProducer {
}
private String updateJwsJsonSignedDocument(JwsJsonSignatureEntry signature) {
- if (signatures.isEmpty()) {
- jwsJsonSignedDocBuilder.append("{\"payload\":\"" + encodedPayload + "\"");
- jwsJsonSignedDocBuilder.append(",\"signatures\":[");
- } else {
- jwsJsonSignedDocBuilder.append(",");
- }
- jwsJsonSignedDocBuilder.append(signature.toJson());
signatures.add(signature);
-
return getJwsJsonSignedDocument();
}
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/85ebf3f7/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java
index 1e75ff9..279ea31 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonSignatureEntry.java
@@ -119,8 +119,13 @@ public class JwsJsonSignatureEntry {
return JwsUtils.validateCriticalHeaders(getUnionHeader());
}
public String toJson() {
+ return toJson(false);
+ }
+ public String toJson(boolean flattenedMode) {
StringBuilder sb = new StringBuilder();
- sb.append("{");
+ if (!flattenedMode) {
+ sb.append("{");
+ }
if (protectedHeader != null) {
sb.append("\"protected\":\"" + protectedHeader.getEncodedHeaderEntries() + "\"");
}
@@ -132,7 +137,9 @@ public class JwsJsonSignatureEntry {
}
sb.append(",");
sb.append("\"signature\":\"" + encodedSignature + "\"");
- sb.append("}");
+ if (!flattenedMode) {
+ sb.append("}");
+ }
return sb.toString();
}
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/85ebf3f7/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducerTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducerTest.java b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducerTest.java
index d6a5fd0..3b5b492 100644
--- a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducerTest.java
+++ b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducerTest.java
@@ -44,6 +44,12 @@ public class JwsJsonProducerTest extends Assert {
+ UNSIGNED_PLAIN_JSON_DOCUMENT_AS_B64URL
+ "\",\"signatures\":[{\"protected\":\"eyJhbGciOiJIUzI1NiJ9\",\"signature\":"
+ "\"NNksREOsFCI1nUQEqzCe6XZFa-bRAge2XXMMAU2Jj2I\"}]}";
+
+ public static final String SIGNED_JWS_JSON_FLAT_DOCUMENT = "{"
+ + "\"payload\":\""
+ + UNSIGNED_PLAIN_JSON_DOCUMENT_AS_B64URL
+ + "\",\"protected\":\"eyJhbGciOiJIUzI1NiJ9\",\"signature\":"
+ + "\"NNksREOsFCI1nUQEqzCe6XZFa-bRAge2XXMMAU2Jj2I\"}";
public static final String DUAL_SIGNED_JWS_JSON_DOCUMENT = "{"
+ "\"payload\":\""
@@ -75,6 +81,18 @@ public class JwsJsonProducerTest extends Assert {
producer.getJwsJsonSignedDocument());
}
@Test
+ public void testSignWithProtectedHeaderOnlyFlat() {
+ JwsJsonProducer producer = new JwsJsonProducer(UNSIGNED_PLAIN_JSON_DOCUMENT, true);
+ JoseHeaders headerEntries = new JoseHeaders();
+ headerEntries.setAlgorithm(JoseConstants.HMAC_SHA_256_ALGO);
+
+ producer.signWith(new HmacJwsSignatureProvider(ENCODED_MAC_KEY_1,
+ JoseConstants.HMAC_SHA_256_ALGO),
+ new JwsJsonProtectedHeader(headerEntries));
+ assertEquals(SIGNED_JWS_JSON_FLAT_DOCUMENT,
+ producer.getJwsJsonSignedDocument());
+ }
+ @Test
public void testDualSignWithProtectedHeaderOnly() {
JwsJsonProducer producer = new JwsJsonProducer(UNSIGNED_PLAIN_JSON_DOCUMENT);
JoseHeaders headerEntries = new JoseHeaders();