Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 5BAAA200C29 for ; Tue, 28 Feb 2017 17:15:26 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 5A210160B7C; Tue, 28 Feb 2017 16:15:26 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 7AEA8160B6A for ; Tue, 28 Feb 2017 17:15:25 +0100 (CET) Received: (qmail 28277 invoked by uid 500); 28 Feb 2017 16:15:24 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 28268 invoked by uid 99); 28 Feb 2017 16:15:24 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 28 Feb 2017 16:15:24 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 8F63BDFCA1; Tue, 28 Feb 2017 16:15:24 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergeyb@apache.org To: commits@cxf.apache.org Message-Id: <47eff14e0436405f84d103986cde0f26@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: cxf git commit: [CXF-6728] Using Jose4J/Santuario code instead Date: Tue, 28 Feb 2017 16:15:24 +0000 (UTC) archived-at: Tue, 28 Feb 2017 16:15:26 -0000 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 Authored: Tue Feb 28 16:15:09 2017 +0000 Committer: Sergey Beryozkin 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; } }