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 2017/02/28 16:15:24 UTC

cxf git commit: [CXF-6728] Using Jose4J/Santuario code instead

Repository: cxf
Updated Branches:
  refs/heads/master 8fa9b8b14 -> c2b13b747


[CXF-6728] Using Jose4J/Santuario code instead


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

Branch: refs/heads/master
Commit: c2b13b7473781c3c1a4225a01c319cf8aa92cd0f
Parents: 8fa9b8b
Author: Sergey Beryozkin <sb...@gmail.com>
Authored: Tue Feb 28 16:15:09 2017 +0000
Committer: Sergey Beryozkin <sb...@gmail.com>
Committed: Tue Feb 28 16:15:09 2017 +0000

----------------------------------------------------------------------
 .../jose/jws/EcDsaJwsSignatureProvider.java     | 80 ++++++++++----------
 .../jose/jws/EcDsaJwsSignatureVerifier.java     | 79 ++++++++++++++-----
 2 files changed, 101 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/c2b13b74/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
index 141602f..6c4bf68 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureProvider.java
@@ -23,6 +23,7 @@ import java.security.Signature;
 import java.security.interfaces.ECPrivateKey;
 import java.security.spec.AlgorithmParameterSpec;
 
+import org.apache.cxf.rs.security.jose.common.JoseException;
 import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
 import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
 
@@ -61,50 +62,53 @@ public class EcDsaJwsSignatureProvider extends PrivateKeyJwsSignatureProvider {
     }
 
     private static byte[] jcaOutputToJoseOutput(int jwsSignatureLen, byte jcaDer[]) {
-        // DER uses a pattern of type-length-value triplets
-        // http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One#Example_encoded_in_DER
+        // Apache2 Licensed Jose4j code which adapts the Apache Santuario XMLSecurity
+        // code and aligns it with JWS/JWS requirements
+        if (jcaDer.length < 8 || jcaDer[0] != 48) {
+            throw new JoseException("Invalid format of ECDSA signature");
+        }
 
-        // The algorithm implementation guarantees the correct DER format so no extra validation
+        int offset;
+        if (jcaDer[1] > 0) {
+            offset = 2;
+        } else if (jcaDer[1] == (byte) 0x81) {
+            offset = 3;
+        } else {
+            throw new JoseException("Invalid format of ECDSA signature");
+        }
 
-        // ECDSA signature production:
-        // 48 (SEQUENCE) + Total Length (1 or 2 bytes, the 1st byte is -127 if 2 bytes)
-        // + R & S triples, where both triples are represented as
-        // 2(INTEGER TYPE) + length + the actual sequence of a given length;
-        // The sequence might have the extra leading zeroes which need to be skipped
-        int requiredPartLen = jwsSignatureLen / 2;
+        byte rLength = jcaDer[offset + 1];
 
-        int rsDataBlockStart = jcaDer[1] == -127 ? 4 : 3;
-        int rPartLen = jcaDer[rsDataBlockStart];
-        int rDataBlockStart = rsDataBlockStart + 1;
-        int rPartLenDiff = rPartLen - requiredPartLen;
-        int rValueStart = rDataBlockStart + getDataBlockOffset(jcaDer, rDataBlockStart, rPartLenDiff);
+        int i;
+        for (i = rLength; i > 0 && jcaDer[(offset + 2 + rLength) - i] == 0; i--) {
+            // complete
+        }
 
-        int sPartStart = rDataBlockStart + rPartLen;
-        int sPartLen = jcaDer[sPartStart + 1];
-        int sPartLenDiff = sPartLen - requiredPartLen;
-        int sDataBlockStart = sPartStart + 2;
-        int sValueStart = sDataBlockStart + getDataBlockOffset(jcaDer, sDataBlockStart, sPartLenDiff);
+        byte sLength = jcaDer[offset + 2 + rLength + 1];
 
-        byte[] result = new byte[jwsSignatureLen];
-        System.arraycopy(jcaDer, rValueStart, result,
-            rPartLenDiff < 0 ? rPartLenDiff * -1 : 0,
-            rPartLenDiff < 0 ? requiredPartLen + rPartLenDiff : requiredPartLen);
-        System.arraycopy(jcaDer, sValueStart, result,
-            sPartLenDiff < 0 ? requiredPartLen + sPartLenDiff * -1 : requiredPartLen,
-            sPartLenDiff < 0 ? requiredPartLen + sPartLenDiff : requiredPartLen);
-        return result;
-    }
-    private static int getDataBlockOffset(byte[] jcaDer, int blockStart, int partLenDiff) {
-        // ECDSA productions have 64, 96 or 132 output lengths. The R and S parts would be 32, 48 or 66 bytes each.
-        // If it is 32 or 48 bytes then we may have occasional extra zeroes in the JCA DER output
-        int i = 0;
-        if (partLenDiff > 0) {
-            while (i < partLenDiff && jcaDer[blockStart + i] == 0) {
-                i++;
-            }
+        int j;
+        for (j = sLength; j > 0 && jcaDer[(offset + 2 + rLength + 2 + sLength) - j] == 0; j--) {
+            // complete
         }
-        return i;
-    }
 
+        int rawLen = Math.max(i, j);
+        rawLen = Math.max(rawLen, jwsSignatureLen / 2);
+
+        if ((jcaDer[offset - 1] & 0xff) != jcaDer.length - offset
+            || (jcaDer[offset - 1] & 0xff) != 2 + rLength + 2 + sLength
+            || jcaDer[offset] != 2
+            || jcaDer[offset + 2 + rLength] != 2) {
+            throw new JoseException("Invalid format of ECDSA signature");
+        }
+        
+        byte concatenatedSignatureBytes[] = new byte[2 * rawLen];
+
+        System.arraycopy(jcaDer, (offset + 2 + rLength) - i, concatenatedSignatureBytes, rawLen - i, i);
+        System.arraycopy(jcaDer, (offset + 2 + rLength + 2 + sLength) - j, 
+                         concatenatedSignatureBytes, 2 * rawLen - j, j);
+
+        return concatenatedSignatureBytes;
+    }
+    
 
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/c2b13b74/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
index 12e7bfe..0c378f5 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/EcDsaJwsSignatureVerifier.java
@@ -24,6 +24,7 @@ import java.security.spec.AlgorithmParameterSpec;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.cxf.rs.security.jose.common.JoseException;
 import org.apache.cxf.rs.security.jose.jwa.AlgorithmUtils;
 import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
 
@@ -64,27 +65,65 @@ public class EcDsaJwsSignatureVerifier extends PublicKeyJwsSignatureVerifier {
     protected boolean isValidAlgorithmFamily(String algo) {
         return AlgorithmUtils.isEcDsaSign(algo);
     }
+    
     private static byte[] signatureToDer(byte joseSig[]) {
-        int partLen = joseSig.length / 2;
-        int rOffset = joseSig[0] < 0 ? 1 : 0;
-        int sOffset = joseSig[partLen] < 0 ? 1 : 0;
-        int rPartLen = partLen + rOffset;
-        int sPartLen = partLen + sOffset;
-        int totalLenBytesCount = joseSig.length > 127 ? 2 : 1;
-        int rPartStart = 1 + totalLenBytesCount + 2;
-        byte[] der = new byte[rPartStart + 2 + rPartLen + sPartLen];
-        der[0] = 48;
-        if (totalLenBytesCount == 2) {
-            der[1] = -127;
+        // Apache2 Licensed Jose4j code which adapts the Apache Santuario XMLSecurity
+        // code and aligns it with JWS/JWS requirements
+        int rawLen = joseSig.length / 2;
+
+        int i;
+
+        for (i = rawLen; i > 0 && joseSig[rawLen - i] == 0; i--) {
+            // complete
+        }
+
+        int j = i;
+
+        if (joseSig[rawLen - i] < 0) {
+            j += 1;
+        }
+
+        int k;
+
+        for (k = rawLen; k > 0 && joseSig[2 * rawLen - k] == 0; k--) {
+            // complete
+        }
+
+        int l = k;
+
+        if (joseSig[2 * rawLen - k] < 0) {
+            l += 1;
+        }
+
+        int len = 2 + j + 2 + l;
+        if (len > 255) {
+            throw new JoseException("Invalid format of ECDSA signature");
         }
-        der[totalLenBytesCount] = (byte)(der.length - (1 + totalLenBytesCount));
-        der[totalLenBytesCount + 1] = 2;
-        der[totalLenBytesCount + 2] = (byte)rPartLen;
-        int sPartStart = rPartStart + rPartLen;
-        der[sPartStart] = 2;
-        der[sPartStart + 1] = (byte)sPartLen;
-        System.arraycopy(joseSig, 0, der, rPartStart + rOffset, partLen);
-        System.arraycopy(joseSig, partLen, der, sPartStart + 2 + sOffset, partLen);
-        return der;
+        int offset;
+        byte derEncodedSignatureBytes[];
+        if (len < 128) {
+            derEncodedSignatureBytes = new byte[2 + 2 + j + 2 + l];
+            offset = 1;
+        } else {
+            derEncodedSignatureBytes = new byte[3 + 2 + j + 2 + l];
+            derEncodedSignatureBytes[1] = (byte) 0x81;
+            offset = 2;
+        }
+
+        derEncodedSignatureBytes[0] = 48;
+        derEncodedSignatureBytes[offset++] = (byte) len;
+        derEncodedSignatureBytes[offset++] = 2;
+        derEncodedSignatureBytes[offset++] = (byte) j;
+
+        System.arraycopy(joseSig, rawLen - i, derEncodedSignatureBytes, (offset + j) - i, i);
+
+        offset += j;
+
+        derEncodedSignatureBytes[offset++] = 2;
+        derEncodedSignatureBytes[offset++] = (byte) l;
+
+        System.arraycopy(joseSig, 2 * rawLen - k, derEncodedSignatureBytes, (offset + l) - k, k);
+
+        return derEncodedSignatureBytes;
     }
 }