cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject git commit: [CXF-6053] Applying a second part of the modified patch on behalf of Daniel Torkian and Luigi Lo Iacono
Date Mon, 20 Oct 2014 15:33:17 GMT
Repository: cxf
Updated Branches:
  refs/heads/master cd809b852 -> dfe481df4


[CXF-6053] Applying a second part of the modified patch on behalf of Daniel Torkian and Luigi
Lo Iacono


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

Branch: refs/heads/master
Commit: dfe481df4b2eb5129073bd82737373ef00a16f28
Parents: cd809b8
Author: Sergey Beryozkin <sberyozkin@talend.com>
Authored: Mon Oct 20 16:32:57 2014 +0100
Committer: Sergey Beryozkin <sberyozkin@talend.com>
Committed: Mon Oct 20 16:32:57 2014 +0100

----------------------------------------------------------------------
 .../rs/security/jose/jws/JwsJsonConsumer.java   |   7 +-
 .../rs/security/jose/jws/JwsJsonProducer.java   | 118 +++++++++++++++++++
 .../jose/jws/JwsJsonProtectedHeader.java        |  13 +-
 .../jose/jws/JwsJsonSignatureEntry.java         |  43 +++++--
 .../jose/jws/JwsJsonUnprotectedHeader.java      |  10 +-
 .../security/jose/jws/JwsJsonProducerTest.java  |  93 +++++++++++++++
 6 files changed, 251 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/dfe481df/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 45069b3..f22bb89 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
@@ -60,9 +60,6 @@ public class JwsJsonConsumer {
             @SuppressWarnings("unchecked")
             Map<String, Object> header = (Map<String, Object>)signatureEntry.get("header");
             String signature = (String)signatureEntry.get("signature");
-            if (protectedHeader == null && header == null || signature == null) {
-                throw new SecurityException("Invalid security entry");
-            }
             JwsJsonSignatureEntry signatureObject = 
                 new JwsJsonSignatureEntry(encodedJwsPayload, 
                                           protectedHeader, 
@@ -97,5 +94,7 @@ public class JwsJsonConsumer {
     public boolean verifySignatureWith(JsonWebKey key) {
         return verifySignatureWith(JwsUtils.getSignatureVerifier(key));
     }
-    
+    public JwsJsonProducer toProducer() {
+        return new JwsJsonProducer(getDecodedJwsPayload(), signatureEntries);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/dfe481df/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
new file mode 100644
index 0000000..740ded1
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducer.java
@@ -0,0 +1,118 @@
+/**
+ * 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.
+ */
+package org.apache.cxf.rs.security.jose.jws;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.cxf.common.util.Base64UrlUtility;
+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 String plainPayload;
+    private String encodedPayload;
+    private StringBuilder jwsJsonSignedDocBuilder = new StringBuilder();
+    private List<JwsJsonSignatureEntry> signatures = new LinkedList<JwsJsonSignatureEntry>();
+    public JwsJsonProducer(String tbsDocument) {
+        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() {
+        if (signatures.isEmpty()) { 
+            throw new SecurityException("Signature is not available");
+        }
+        return jwsJsonSignedDocBuilder.toString() + "]}";
+    }
+    public List<JwsJsonSignatureEntry> getSignatureEntries() {
+        return Collections.unmodifiableList(signatures);
+    }
+    public String signWith(JwsSignatureProvider signer) {
+        JoseHeaders headers = new JoseHeaders();
+        headers.setAlgorithm(signer.getAlgorithm());
+        return signWith(signer, new JwsJsonProtectedHeader(headers));
+    }
+    public String signWith(JwsSignatureProvider signer, 
+                           JwsJsonProtectedHeader protectedHeader) {
+        return signWith(signer, protectedHeader, null);
+    }
+    public String signWith(JsonWebKey jwk) {
+        return signWith(JwsUtils.getSignatureProvider(jwk));
+    }
+    public String signWith(JwsSignatureProvider signer,
+                           JwsJsonProtectedHeader protectedHeader,
+                           JwsJsonUnprotectedHeader unprotectedHeader) {
+        JoseHeaders unionHeaders = new JoseHeaders();
+         
+        if (protectedHeader != null) {
+            unionHeaders.asMap().putAll(protectedHeader.getHeaderEntries().asMap());
+        }
+        if (unprotectedHeader != null) {
+            if (!Collections.disjoint(unionHeaders.asMap().keySet(), 
+                                     unprotectedHeader.getHeaderEntries().asMap().keySet()))
{
+                throw new SecurityException("Protected and unprotected headers have duplicate
values");
+            }
+            unionHeaders.asMap().putAll(unprotectedHeader.getHeaderEntries().asMap());
+        }
+        if (unionHeaders.getAlgorithm() == null) {
+            throw new SecurityException("Algorithm header is not set");
+        }
+        JwsSignature worker = signer.createJwsSignature(unionHeaders);
+        String sequenceToBeSigned = protectedHeader.getEncodedHeaderEntries() 
+            + "." + getUnsignedEncodedPayload();
+        byte[] bytesToBeSigned = StringUtils.toBytesUTF8(sequenceToBeSigned);
+        worker.update(bytesToBeSigned, 0, bytesToBeSigned.length);
+        byte[] signatureBytes = worker.sign();
+        String encodedSignatureBytes = Base64UrlUtility.encode(signatureBytes);
+        JwsJsonSignatureEntry signature = 
+            new JwsJsonSignatureEntry(encodedPayload, 
+                                      protectedHeader.getEncodedHeaderEntries(),
+                                      encodedSignatureBytes,
+                                      unprotectedHeader); 
+        return updateJwsJsonSignedDocument(signature);
+    }
+    
+    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/dfe481df/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProtectedHeader.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProtectedHeader.java
b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProtectedHeader.java
index 81b3bf6..05cecdb 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProtectedHeader.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProtectedHeader.java
@@ -49,17 +49,8 @@ public class JwsJsonProtectedHeader {
     public Object getHeader(String name) {
         return headerEntries.getHeader(name);
     }
-    public String toJson() {
-        if (headerEntries == null) {
-            return "";
-        }
-        //The "protected" member MUST be present and contain the value
-        // BASE64URL(UTF8(JWS Protected Header)) when the JWS Protected
-        // Header value is non-empty; otherwise, it MUST be absent. These
-        // Header Parameter values are integrity protected.
-        return "\"protected\":\""
-               + Base64UrlUtility.encode(writer.headersToJson(headerEntries))
-               + "\"";
+    public String getEncodedHeaderEntries() {
+        return Base64UrlUtility.encode(writer.headersToJson(headerEntries));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/dfe481df/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 8b73f45..b9f37b5 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
@@ -33,12 +33,16 @@ public class JwsJsonSignatureEntry {
     private String encodedSignature;
     private JwsJsonProtectedHeader protectedHeader;
     private JwsJsonUnprotectedHeader unprotectedHeader;
-    private JoseHeaders unionHeader;
+    private JoseHeaders unionHeaders;
       
     public JwsJsonSignatureEntry(String encodedJwsPayload,
                                  String encodedProtectedHeader,
                                  String encodedSignature,
                                  JwsJsonUnprotectedHeader unprotectedHeader) {
+        if (encodedProtectedHeader == null && unprotectedHeader == null || encodedSignature
== null) {
+            throw new SecurityException("Invalid security entry");
+        }
+        
         this.encodedJwsPayload = encodedJwsPayload;
         this.encodedProtectedHeader = encodedProtectedHeader;
         this.encodedSignature = encodedSignature;
@@ -48,14 +52,18 @@ public class JwsJsonSignatureEntry {
         prepare();
     }
     private void prepare() {
-        JoseHeaders joseProtectedHeader = getProtectedHeader().getHeaderEntries();
-        JoseHeaders joseUnprotectedHeader = getUnprotectedHeader().getHeaderEntries();
-        if (!Collections.disjoint(joseProtectedHeader.asMap().keySet(), 
-                                  joseUnprotectedHeader.asMap().keySet())) {
-            throw new SecurityException("Protected and unprotected headers have duplicate
values");
+        unionHeaders = new JoseHeaders();
+        
+        if (protectedHeader != null) {
+            unionHeaders.asMap().putAll(protectedHeader.getHeaderEntries().asMap());
+        }
+        if (unprotectedHeader != null) {
+            if (!Collections.disjoint(unionHeaders.asMap().keySet(), 
+                                     unprotectedHeader.getHeaderEntries().asMap().keySet()))
{
+                throw new SecurityException("Protected and unprotected headers have duplicate
values");
+            }
+            unionHeaders.asMap().putAll(unprotectedHeader.getHeaderEntries().asMap());
         }
-        unionHeader = new JoseHeaders(joseProtectedHeader);
-        unionHeader.asMap().putAll(joseUnprotectedHeader.asMap());
     }
     public String getEncodedJwsPayload() {
         return encodedJwsPayload;
@@ -76,7 +84,7 @@ public class JwsJsonSignatureEntry {
         return unprotectedHeader;
     }
     public JoseHeaders getUnionHeader() {
-        return unionHeader;
+        return unionHeaders;
     }
     public String getEncodedSignature() {
         return encodedSignature;
@@ -100,4 +108,21 @@ public class JwsJsonSignatureEntry {
     public boolean verifySignatureWith(JsonWebKey key) {
         return verifySignatureWith(JwsUtils.getSignatureVerifier(key));
     }
+    public String toJson() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("{");
+        if (protectedHeader != null) {
+            sb.append("\"protected\":\"" + protectedHeader.getEncodedHeaderEntries() + "\"");
+        }
+        if (unprotectedHeader != null) {
+            if (protectedHeader != null) {
+                sb.append(",");
+            }
+            sb.append("\"header\":\"" + unprotectedHeader.toJson() + "\"");
+        }
+        sb.append(",");
+        sb.append("\"signature\":\"" + encodedSignature + "\"");
+        sb.append("}");
+        return sb.toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/dfe481df/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonUnprotectedHeader.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonUnprotectedHeader.java
b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonUnprotectedHeader.java
index 7fdd54a..90a7d1f 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonUnprotectedHeader.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsJsonUnprotectedHeader.java
@@ -53,14 +53,6 @@ public class JwsJsonUnprotectedHeader {
         return headerEntries;
     }
     public String toJson() {
-        // The "header" member MUST be present and contain the value JWS
-        // Unprotected Header when the JWS Unprotected Header value is non-
-        // empty; otherwise, it MUST be absent. This value is represented as
-        // an unencoded JSON object, rather than as a string. These Header
-        // Parameter values are not integrity protected.
-        if (headerEntries == null) {
-            return "";
-        }
-        return "\"header\":" + writer.headersToJson(headerEntries);
+        return writer.headersToJson(headerEntries);
     } 
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/dfe481df/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
new file mode 100644
index 0000000..d6a5fd0
--- /dev/null
+++ b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsJsonProducerTest.java
@@ -0,0 +1,93 @@
+/**
+ * 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.
+ */
+package org.apache.cxf.rs.security.jose.jws;
+import org.apache.cxf.rs.security.jose.JoseConstants;
+import org.apache.cxf.rs.security.jose.JoseHeaders;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class JwsJsonProducerTest extends Assert {
+
+    public static final String ENCODED_MAC_KEY_1 = "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75"
+                       + "aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow";
+
+    public static final String ENCODED_MAC_KEY_2 = "09Y_RK7l5rAY9QY7EblYQNuYbu9cy1j7ovCbkeIyAKN8LIeRL-3H8g"
+                       + "c8kZSYzAQ1uTRC_egZ_8cgZSZa9T5nmQ";
+
+    public static final String UNSIGNED_PLAIN_JSON_DOCUMENT = "{"
+                       + " \"from\": \"user\"," + " \"to\": \"developer\","
+                       + " \"msg\": \"good job!\" " + "}";
+
+    public static final String UNSIGNED_PLAIN_JSON_DOCUMENT_AS_B64URL = "eyAiZnJvbSI6ICJ1c2VyIiwgInRvIjogI"
+                       + "mRldmVsb3BlciIsICJtc2ciOiAiZ29vZCBqb2IhIiB9";
+
+       
+    public static final String SIGNED_JWS_JSON_DOCUMENT = "{"
+                       + "\"payload\":\""
+                       + UNSIGNED_PLAIN_JSON_DOCUMENT_AS_B64URL
+                       + "\",\"signatures\":[{\"protected\":\"eyJhbGciOiJIUzI1NiJ9\",\"signature\":"
+                       + "\"NNksREOsFCI1nUQEqzCe6XZFa-bRAge2XXMMAU2Jj2I\"}]}";
+       
+    public static final String DUAL_SIGNED_JWS_JSON_DOCUMENT = "{"
+                       + "\"payload\":\""
+                       + UNSIGNED_PLAIN_JSON_DOCUMENT_AS_B64URL
+                       + "\",\"signatures\":[{\"protected\":\"eyJhbGciOiJIUzI1NiJ9\","
+                       + "\"signature\":\"NNksREOsFCI1nUQEqzCe6XZFa-bRAge2XXMMAU2Jj2I\"},"
+                       + "{\"protected\":\"eyJhbGciOiJIUzI1NiJ9\","
+                       + "\"signature\":\"KY2r_Gubar7G86fVyrA7I2-69KA7faKDmebfCCmibdI\"}]}";
+
+    @Test
+    public void testSignPlainJsonDocumentPayloadConstruction() {
+        JwsJsonProducer producer = new JwsJsonProducer(UNSIGNED_PLAIN_JSON_DOCUMENT);
+
+        assertEquals(UNSIGNED_PLAIN_JSON_DOCUMENT_AS_B64URL,
+                      producer.getUnsignedEncodedPayload());
+    }
+
+       
+    @Test
+    public void testSignWithProtectedHeaderOnly() {
+        JwsJsonProducer producer = new JwsJsonProducer(UNSIGNED_PLAIN_JSON_DOCUMENT);
+        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_DOCUMENT,
+                     producer.getJwsJsonSignedDocument());
+    }
+    @Test
+    public void testDualSignWithProtectedHeaderOnly() {
+        JwsJsonProducer producer = new JwsJsonProducer(UNSIGNED_PLAIN_JSON_DOCUMENT);
+        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));
+        producer.signWith(new HmacJwsSignatureProvider(ENCODED_MAC_KEY_2,
+                          JoseConstants.HMAC_SHA_256_ALGO),
+                          new JwsJsonProtectedHeader(headerEntries));
+        assertEquals(DUAL_SIGNED_JWS_JSON_DOCUMENT,
+                     producer.getJwsJsonSignedDocument());
+    }
+
+}


Mime
View raw message