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;
}
}