cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject cxf git commit: Support for unencoded detached payloads in case of JWS compact
Date Sun, 06 Sep 2015 17:36:53 GMT
Repository: cxf
Updated Branches:
  refs/heads/master 2fc62cf0f -> 56b99bada


Support for unencoded detached payloads in case of JWS compact


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

Branch: refs/heads/master
Commit: 56b99bada23c3b142b5d99da12c4256dda4f3dd4
Parents: 2fc62cf
Author: Sergey Beryozkin <sberyozkin@gmail.com>
Authored: Sun Sep 6 18:36:35 2015 +0100
Committer: Sergey Beryozkin <sberyozkin@gmail.com>
Committed: Sun Sep 6 18:36:35 2015 +0100

----------------------------------------------------------------------
 .../security/jose/jws/JwsCompactConsumer.java   | 47 +++++++++++++-------
 .../security/jose/jws/JwsCompactProducer.java   | 38 +++++++++++-----
 .../jose/jws/JwsJsonSignatureEntry.java         |  3 +-
 .../cxf/rs/security/jose/jws/JwsUtils.java      |  3 ++
 .../jose/cookbook/JwsJoseCookBookTest.java      |  8 ++--
 .../jose/jws/JwsCompactReaderWriterTest.java    | 15 +++++--
 6 files changed, 78 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/56b99bad/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
index 4c721c5..93f6d89 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactConsumer.java
@@ -36,14 +36,17 @@ public class JwsCompactConsumer {
     private String encodedSequence;
     private String encodedSignature;
     private String headersJson;
+    private String jwsPayload;
     private String decodedJwsPayload;
+    private JwsHeaders jwsHeaders;
+    private boolean detached;
     public JwsCompactConsumer(String encodedJws) {
         this(encodedJws, null, null);
     }
-    public JwsCompactConsumer(String encodedJws, String encodedDetachedPayload) {
-        this(encodedJws, encodedDetachedPayload, null);
+    public JwsCompactConsumer(String encodedJws, String detachedPayload) {
+        this(encodedJws, detachedPayload, null);
     }
-    protected JwsCompactConsumer(String encodedJws, String encodedDetachedPayload, JsonMapObjectReaderWriter
r) {
+    protected JwsCompactConsumer(String encodedJws, String detachedPayload, JsonMapObjectReaderWriter
r) {
         if (r != null) {
             this.reader = r;
         }
@@ -58,17 +61,17 @@ public class JwsCompactConsumer {
         } else {
             encodedSignature = parts[2];
         }
-        String encodedJwsPayload = parts[1];
-        if (encodedDetachedPayload != null) {
-            if (!StringUtils.isEmpty(encodedJwsPayload)) {
+        jwsPayload = parts[1];
+        if (detachedPayload != null) {
+            if (!StringUtils.isEmpty(jwsPayload)) {
                 LOG.warning("Compact JWS includes a payload expected to be detached");
                 throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS);
             }
-            encodedJwsPayload = encodedDetachedPayload;
+            detached = true;
+            jwsPayload = detachedPayload;
         }
-        encodedSequence = parts[0] + "." + encodedJwsPayload;
+        encodedSequence = parts[0] + "." + jwsPayload;
         headersJson = JoseUtils.decodeToString(parts[0]);
-        decodedJwsPayload = JoseUtils.decodeToString(encodedJwsPayload);
     }
     public String getUnsignedEncodedSequence() {
         return encodedSequence;
@@ -80,21 +83,35 @@ public class JwsCompactConsumer {
         return headersJson;
     }
     public String getDecodedJwsPayload() {
+        if (decodedJwsPayload == null) {
+            if (JwsUtils.isPayloadUnencoded(jwsHeaders)) {
+                decodedJwsPayload = jwsPayload;
+            } else {
+                decodedJwsPayload = JoseUtils.decodeToString(jwsPayload);
+            }
+        }
         return decodedJwsPayload;
     }
     public byte[] getDecodedJwsPayloadBytes() {
-        return StringUtils.toBytesUTF8(decodedJwsPayload);
+        return StringUtils.toBytesUTF8(getDecodedJwsPayload());
     }
     public byte[] getDecodedSignature() {
         return encodedSignature.isEmpty() ? new byte[]{} : JoseUtils.decode(encodedSignature);
     }
     public JwsHeaders getJwsHeaders() {
-        JsonMapObject joseHeaders = reader.fromJsonToJsonObject(headersJson);
-        if (joseHeaders.getUpdateCount() != null) {
-            LOG.warning("Duplicate headers have been detected");
-            throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS);
+        if (jwsHeaders == null) {
+            JsonMapObject joseHeaders = reader.fromJsonToJsonObject(headersJson);
+            if (joseHeaders.getUpdateCount() != null) {
+                LOG.warning("Duplicate headers have been detected");
+                throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS);
+            }
+            jwsHeaders = new JwsHeaders(joseHeaders.asMap());
+            if (JwsUtils.isPayloadUnencoded(jwsHeaders) && !detached) {
+                LOG.warning("Only detached payload can be unencoded");
+                throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS);
+            }
         }
-        return new JwsHeaders(joseHeaders.asMap());
+        return jwsHeaders;
     }
     public boolean verifySignatureWith(JwsSignatureVerifier validator) {
         try {

http://git-wip-us.apache.org/repos/asf/cxf/blob/56b99bad/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
index 20213ea..9795c10 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsCompactProducer.java
@@ -31,18 +31,30 @@ public class JwsCompactProducer {
     private JwsHeaders headers;
     private String plainJwsPayload;
     private String signature;
+    private boolean detached;
     public JwsCompactProducer(String plainJwsPayload) {
-        this(null, null, plainJwsPayload);
+        this(plainJwsPayload, false);
+    }
+    public JwsCompactProducer(String plainJwsPayload, boolean detached) {
+        this(null, null, plainJwsPayload, detached);
     }
     public JwsCompactProducer(JwsHeaders headers, String plainJwsPayload) {
-        this(headers, null, plainJwsPayload);
+        this(headers, plainJwsPayload, false);
+    }
+    public JwsCompactProducer(JwsHeaders headers, String plainJwsPayload, boolean detached)
{
+        this(headers, null, plainJwsPayload, detached);
     }
     protected JwsCompactProducer(JwsHeaders headers, JsonMapObjectReaderWriter w, String
plainJwsPayload) {
+        this(headers, w, plainJwsPayload, false);
+    }    
+    protected JwsCompactProducer(JwsHeaders headers, JsonMapObjectReaderWriter w, String
plainJwsPayload, 
+                                 boolean detached) {    
         this.headers = headers;
         if (w != null) {
             this.writer = w;
         }
         this.plainJwsPayload = plainJwsPayload;
+        this.detached = detached;
     }
     public JwsHeaders getJwsHeaders() {
         if (headers == null) {
@@ -51,27 +63,31 @@ public class JwsCompactProducer {
         return headers;
     }
     public String getUnsignedEncodedJws() {
-        return getUnsignedEncodedJws(false);
-    }
-    private String getUnsignedEncodedJws(boolean detached) {
         checkAlgorithm();
         return Base64UrlUtility.encode(writer.toJson(getJwsHeaders())) 
                + "." 
                + (detached ? "" : Base64UrlUtility.encode(plainJwsPayload));
     }
+    private String getSigningInput() {
+        checkAlgorithm();
+        boolean unencoded = JwsUtils.isPayloadUnencoded(getJwsHeaders());
+        if (unencoded && !detached) {
+            throw new JwsException(JwsException.Error.INVALID_COMPACT_JWS);
+        }
+        return Base64UrlUtility.encode(writer.toJson(getJwsHeaders())) 
+               + "." 
+               + (unencoded ? plainJwsPayload : Base64UrlUtility.encode(plainJwsPayload));
+    }
     public String getEncodedSignature() {
         return signature;
     }
     public String getSignedEncodedJws() {
-        return getSignedEncodedJws(false);
-    }
-    public String getSignedEncodedJws(boolean detached) {
         checkAlgorithm();
         boolean noSignature = StringUtils.isEmpty(signature);
         if (noSignature && !isPlainText()) {
             throw new IllegalStateException("Signature is not available");
         }
-        return getUnsignedEncodedJws(detached) + "." + (noSignature ? "" : signature);
+        return getUnsignedEncodedJws() + "." + (noSignature ? "" : signature);
     }
     public String signWith(JsonWebKey jwk) {
         return signWith(JwsUtils.getSignatureProvider(jwk, 
@@ -88,7 +104,7 @@ public class JwsCompactProducer {
     }
     
     public String signWith(JwsSignatureProvider signer) {
-        byte[] bytes = StringUtils.toBytesUTF8(getUnsignedEncodedJws());
+        byte[] bytes = StringUtils.toBytesUTF8(getSigningInput());
         byte[] sig = signer.sign(getJwsHeaders(), bytes);
         return setSignatureBytes(sig);
     }
@@ -114,7 +130,7 @@ public class JwsCompactProducer {
     }
     private void checkAlgorithm() {
         if (getAlgorithm() == null) {
-            throw new IllegalStateException("Algorithm header is not set");
+            throw new JwsException(JwsException.Error.INVALID_ALGORITHM);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/56b99bad/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 4a2de5f..dd2e590 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
@@ -77,8 +77,7 @@ public class JwsJsonSignatureEntry {
         return jwsPayload;
     }
     public String getDecodedJwsPayload() {
-        if (protectedHeader == null 
-            || protectedHeader.getPayloadEncodingStatus() != Boolean.FALSE) {
+        if (protectedHeader == null || !JwsUtils.isPayloadUnencoded(protectedHeader)) {
             return JoseUtils.decodeToString(jwsPayload);
         } else {
             return jwsPayload;

http://git-wip-us.apache.org/repos/asf/cxf/blob/56b99bad/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 73b291e..e959e6e 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
@@ -390,4 +390,7 @@ public final class JwsUtils {
                                                                   RSSEC_SIGNATURE_IN_PROPS,
RSSEC_SIGNATURE_PROPS);
         KeyManagementUtils.validateCertificateChain(props, certs);
     }
+    public static boolean isPayloadUnencoded(JwsHeaders jwsHeaders) {
+        return jwsHeaders.getPayloadEncodingStatus() == Boolean.FALSE;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/56b99bad/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/cookbook/JwsJoseCookBookTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/cookbook/JwsJoseCookBookTest.java
b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/cookbook/JwsJoseCookBookTest.java
index f606beb..1c1bb04 100644
--- a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/cookbook/JwsJoseCookBookTest.java
+++ b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/cookbook/JwsJoseCookBookTest.java
@@ -508,20 +508,20 @@ public class JwsJoseCookBookTest {
     }
     @Test
     public void testDetachedHMACSignature() throws Exception {
-        JwsCompactProducer compactProducer = new JwsCompactProducer(PAYLOAD);
+        JwsCompactProducer compactProducer = new JwsCompactProducer(PAYLOAD, true);
         compactProducer.getJwsHeaders().setSignatureAlgorithm(SignatureAlgorithm.HS256);
         compactProducer.getJwsHeaders().setKeyId(HMAC_KID_VALUE);
         JsonMapObjectReaderWriter reader = new JsonMapObjectReaderWriter();
         assertEquals(reader.toJson(compactProducer.getJwsHeaders().asMap()), HMAC_SIGNATURE_PROTECTED_HEADER_JSON);
         assertEquals(compactProducer.getUnsignedEncodedJws(),
-                HMAC_SIGNATURE_PROTECTED_HEADER + "." + ENCODED_PAYLOAD);
+                HMAC_SIGNATURE_PROTECTED_HEADER + ".");
         JsonWebKeys jwks = readKeySet("cookbookSecretSet.txt");
         List<JsonWebKey> keys = jwks.getKeys();
         JsonWebKey key = keys.get(0);
         compactProducer.signWith(key);
-        assertEquals(compactProducer.getSignedEncodedJws(true), DETACHED_HMAC_JWS);
+        assertEquals(compactProducer.getSignedEncodedJws(), DETACHED_HMAC_JWS);
         JwsCompactConsumer compactConsumer =
-                new JwsCompactConsumer(compactProducer.getSignedEncodedJws(true), ENCODED_PAYLOAD);
+                new JwsCompactConsumer(compactProducer.getSignedEncodedJws(), ENCODED_PAYLOAD);
         assertTrue(compactConsumer.verifySignatureWith(key, SignatureAlgorithm.HS256));
 
         JwsJsonProducer jsonProducer = new JwsJsonProducer(PAYLOAD);

http://git-wip-us.apache.org/repos/asf/cxf/blob/56b99bad/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsCompactReaderWriterTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsCompactReaderWriterTest.java
b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsCompactReaderWriterTest.java
index 0759c61..64f04ce 100644
--- a/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsCompactReaderWriterTest.java
+++ b/rt/rs/security/jose/src/test/java/org/apache/cxf/rs/security/jose/jws/JwsCompactReaderWriterTest.java
@@ -42,13 +42,12 @@ import org.apache.cxf.rt.security.crypto.CryptoUtils;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
 import org.junit.Assert;
-import org.junit.Ignore;
 import org.junit.Test;
 
 public class JwsCompactReaderWriterTest extends Assert {
     
     public static final String TOKEN_WITH_DETACHED_UNENCODED_PAYLOAD =
-        "eyJhbGciOiJIUzI1NiJ9..GsyM6AQJbQHY8aQKCbZSPJHzMRWo3HKIlcDuXof7nqs";
+        "eyJhbGciOiJIUzI1NiIsImI2NCI6ZmFsc2V9..GsyM6AQJbQHY8aQKCbZSPJHzMRWo3HKIlcDuXof7nqs";
     public static final String UNSIGNED_PLAIN_DOCUMENT = "$.02";
     
     public static final String ENCODED_TOKEN_SIGNED_BY_MAC = 
@@ -110,11 +109,19 @@ public class JwsCompactReaderWriterTest extends Assert {
         assertEquals(ENCODED_TOKEN_SIGNED_BY_MAC, jws.getSignedEncodedJws());
     }
     @Test
-    @Ignore
     public void testWriteReadJwsUnencodedPayload() throws Exception {
         JwsHeaders headers = new JwsHeaders(SignatureAlgorithm.HS256);
         headers.setPayloadEncodingStatus(false);
-        //JwsCompactProducer producer = new JwsCompactProducer(UNSIGNED_PLAIN_DOCUMENT);
+        JwsCompactProducer producer = new JwsCompactProducer(headers, 
+                                                             UNSIGNED_PLAIN_DOCUMENT, 
+                                                             true);
+        producer.signWith(new HmacJwsSignatureProvider(ENCODED_MAC_KEY, SignatureAlgorithm.HS256));
+        assertEquals(TOKEN_WITH_DETACHED_UNENCODED_PAYLOAD, producer.getSignedEncodedJws());
+        JwsCompactConsumer consumer = 
+            new JwsCompactConsumer(TOKEN_WITH_DETACHED_UNENCODED_PAYLOAD, UNSIGNED_PLAIN_DOCUMENT);
+        
+        assertTrue(consumer.verifySignatureWith(
+            new HmacJwsSignatureVerifier(ENCODED_MAC_KEY, SignatureAlgorithm.HS256)));
     }
     @Test
     public void testWriteReadJwsUnsigned() throws Exception {


Mime
View raw message