8225745: NoSuchAlgorithmException exception for SHA256withECDSA with RSASSA-PSS support
Fixed SignatureUtil and ECDSA signature impl to handle EC parameters Reviewed-by: weijun
This commit is contained in:
parent
27c77d3d29
commit
175faeeadf
src
java.base/share/classes/sun/security/util
jdk.crypto.ec/share/classes/sun/security/ec
test/jdk/sun/security/x509/X509CertImpl
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -104,21 +104,10 @@ public class CurveDB {
|
|||||||
if (namedCurve.getCurve().getField().getFieldSize() != fieldSize) {
|
if (namedCurve.getCurve().getField().getFieldSize() != fieldSize) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (namedCurve.getCurve().equals(params.getCurve()) == false) {
|
if (ECUtil.equals(namedCurve, params)) {
|
||||||
continue;
|
// everything matches our named curve, return it
|
||||||
|
return namedCurve;
|
||||||
}
|
}
|
||||||
if (namedCurve.getGenerator().equals(params.getGenerator()) ==
|
|
||||||
false) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (namedCurve.getOrder().equals(params.getOrder()) == false) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (namedCurve.getCofactor() != params.getCofactor()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// everything matches our named curve, return it
|
|
||||||
return namedCurve;
|
|
||||||
}
|
}
|
||||||
// no match found
|
// no match found
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -32,7 +32,7 @@ import java.security.interfaces.*;
|
|||||||
import java.security.spec.*;
|
import java.security.spec.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class ECUtil {
|
public final class ECUtil {
|
||||||
|
|
||||||
// Used by SunPKCS11 and SunJSSE.
|
// Used by SunPKCS11 and SunJSSE.
|
||||||
public static ECPoint decodePoint(byte[] data, EllipticCurve curve)
|
public static ECPoint decodePoint(byte[] data, EllipticCurve curve)
|
||||||
@ -220,6 +220,21 @@ public class ECUtil {
|
|||||||
return nameSpec.getName();
|
return nameSpec.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean equals(ECParameterSpec spec1, ECParameterSpec spec2) {
|
||||||
|
if (spec1 == spec2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spec1 == null || spec2 == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (spec1.getCofactor() == spec2.getCofactor() &&
|
||||||
|
spec1.getOrder().equals(spec2.getOrder()) &&
|
||||||
|
spec1.getCurve().equals(spec2.getCurve()) &&
|
||||||
|
spec1.getGenerator().equals(spec2.getGenerator()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Convert the concatenation R and S in into their DER encoding
|
// Convert the concatenation R and S in into their DER encoding
|
||||||
public static byte[] encodeSignature(byte[] signature) throws SignatureException {
|
public static byte[] encodeSignature(byte[] signature) throws SignatureException {
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ package sun.security.util;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.spec.*;
|
import java.security.spec.*;
|
||||||
|
import java.util.Locale;
|
||||||
import sun.security.rsa.RSAUtil;
|
import sun.security.rsa.RSAUtil;
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
|
|
||||||
@ -74,14 +75,9 @@ public class SignatureUtil {
|
|||||||
AlgorithmParameters params)
|
AlgorithmParameters params)
|
||||||
throws ProviderException {
|
throws ProviderException {
|
||||||
|
|
||||||
sigName = checkName(sigName);
|
sigName = checkName(sigName).toUpperCase(Locale.ENGLISH);
|
||||||
AlgorithmParameterSpec paramSpec = null;
|
AlgorithmParameterSpec paramSpec = null;
|
||||||
if (params != null) {
|
if (params != null) {
|
||||||
if (sigName.toUpperCase().indexOf("RSA") == -1) {
|
|
||||||
throw new ProviderException
|
|
||||||
("Unrecognized algorithm for signature parameters " +
|
|
||||||
sigName);
|
|
||||||
}
|
|
||||||
// AlgorithmParameters.getAlgorithm() may returns oid if it's
|
// AlgorithmParameters.getAlgorithm() may returns oid if it's
|
||||||
// created during DER decoding. Convert to use the standard name
|
// created during DER decoding. Convert to use the standard name
|
||||||
// before passing it to RSAUtil
|
// before passing it to RSAUtil
|
||||||
@ -93,7 +89,20 @@ public class SignatureUtil {
|
|||||||
throw new ProviderException(e);
|
throw new ProviderException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paramSpec = RSAUtil.getParamSpec(params);
|
|
||||||
|
if (sigName.indexOf("RSA") != -1) {
|
||||||
|
paramSpec = RSAUtil.getParamSpec(params);
|
||||||
|
} else if (sigName.indexOf("ECDSA") != -1) {
|
||||||
|
try {
|
||||||
|
paramSpec = params.getParameterSpec(ECParameterSpec.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ProviderException("Error handling EC parameters", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new ProviderException
|
||||||
|
("Unrecognized algorithm for signature parameters " +
|
||||||
|
sigName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return paramSpec;
|
return paramSpec;
|
||||||
}
|
}
|
||||||
@ -103,17 +112,31 @@ public class SignatureUtil {
|
|||||||
public static AlgorithmParameterSpec getParamSpec(String sigName,
|
public static AlgorithmParameterSpec getParamSpec(String sigName,
|
||||||
byte[] paramBytes)
|
byte[] paramBytes)
|
||||||
throws ProviderException {
|
throws ProviderException {
|
||||||
sigName = checkName(sigName);
|
sigName = checkName(sigName).toUpperCase(Locale.ENGLISH);
|
||||||
AlgorithmParameterSpec paramSpec = null;
|
AlgorithmParameterSpec paramSpec = null;
|
||||||
|
|
||||||
if (paramBytes != null) {
|
if (paramBytes != null) {
|
||||||
if (sigName.toUpperCase().indexOf("RSA") == -1) {
|
if (sigName.indexOf("RSA") != -1) {
|
||||||
|
AlgorithmParameters params =
|
||||||
|
createAlgorithmParameters(sigName, paramBytes);
|
||||||
|
paramSpec = RSAUtil.getParamSpec(params);
|
||||||
|
} else if (sigName.indexOf("ECDSA") != -1) {
|
||||||
|
try {
|
||||||
|
Provider p = Signature.getInstance(sigName).getProvider();
|
||||||
|
paramSpec = ECUtil.getECParameterSpec(p, paramBytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ProviderException("Error handling EC parameters", e);
|
||||||
|
}
|
||||||
|
// ECUtil discards exception and returns null, so we need to check
|
||||||
|
// the returned value
|
||||||
|
if (paramSpec == null) {
|
||||||
|
throw new ProviderException("Error handling EC parameters");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
throw new ProviderException
|
throw new ProviderException
|
||||||
("Unrecognized algorithm for signature parameters " +
|
("Unrecognized algorithm for signature parameters " +
|
||||||
sigName);
|
sigName);
|
||||||
}
|
}
|
||||||
AlgorithmParameters params =
|
|
||||||
createAlgorithmParameters(sigName, paramBytes);
|
|
||||||
paramSpec = RSAUtil.getParamSpec(params);
|
|
||||||
}
|
}
|
||||||
return paramSpec;
|
return paramSpec;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,9 @@ abstract class ECDSASignature extends SignatureSpi {
|
|||||||
// public key, if initialized for verifying
|
// public key, if initialized for verifying
|
||||||
private ECPublicKey publicKey;
|
private ECPublicKey publicKey;
|
||||||
|
|
||||||
|
// signature parameters
|
||||||
|
private ECParameterSpec sigParams = null;
|
||||||
|
|
||||||
// The format. true for the IEEE P1363 format. false (default) for ASN.1
|
// The format. true for the IEEE P1363 format. false (default) for ASN.1
|
||||||
private final boolean p1363Format;
|
private final boolean p1363Format;
|
||||||
|
|
||||||
@ -279,10 +282,14 @@ abstract class ECDSASignature extends SignatureSpi {
|
|||||||
@Override
|
@Override
|
||||||
protected void engineInitVerify(PublicKey publicKey)
|
protected void engineInitVerify(PublicKey publicKey)
|
||||||
throws InvalidKeyException {
|
throws InvalidKeyException {
|
||||||
this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
|
ECPublicKey key = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
|
||||||
|
if (!isCompatible(this.sigParams, key.getParams())) {
|
||||||
|
throw new InvalidKeyException("Key params does not match signature params");
|
||||||
|
}
|
||||||
|
|
||||||
// Should check that the supplied key is appropriate for signature
|
// Should check that the supplied key is appropriate for signature
|
||||||
// algorithm (e.g. P-256 for SHA256withECDSA)
|
// algorithm (e.g. P-256 for SHA256withECDSA)
|
||||||
|
this.publicKey = key;
|
||||||
this.privateKey = null;
|
this.privateKey = null;
|
||||||
resetDigest();
|
resetDigest();
|
||||||
}
|
}
|
||||||
@ -298,10 +305,14 @@ abstract class ECDSASignature extends SignatureSpi {
|
|||||||
@Override
|
@Override
|
||||||
protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
|
protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
|
||||||
throws InvalidKeyException {
|
throws InvalidKeyException {
|
||||||
this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
|
ECPrivateKey key = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
|
||||||
|
if (!isCompatible(this.sigParams, key.getParams())) {
|
||||||
|
throw new InvalidKeyException("Key params does not match signature params");
|
||||||
|
}
|
||||||
|
|
||||||
// Should check that the supplied key is appropriate for signature
|
// Should check that the supplied key is appropriate for signature
|
||||||
// algorithm (e.g. P-256 for SHA256withECDSA)
|
// algorithm (e.g. P-256 for SHA256withECDSA)
|
||||||
|
this.privateKey = key;
|
||||||
this.publicKey = null;
|
this.publicKey = null;
|
||||||
this.random = random;
|
this.random = random;
|
||||||
resetDigest();
|
resetDigest();
|
||||||
@ -354,6 +365,16 @@ abstract class ECDSASignature extends SignatureSpi {
|
|||||||
needsReset = true;
|
needsReset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isCompatible(ECParameterSpec sigParams,
|
||||||
|
ECParameterSpec keyParams) {
|
||||||
|
if (sigParams == null) {
|
||||||
|
// no restriction on key param
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ECUtil.equals(sigParams, keyParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private byte[] signDigestImpl(ECDSAOperations ops, int seedBits,
|
private byte[] signDigestImpl(ECDSAOperations ops, int seedBits,
|
||||||
byte[] digest, ECPrivateKeyImpl privImpl, SecureRandom random)
|
byte[] digest, ECPrivateKeyImpl privImpl, SecureRandom random)
|
||||||
throws SignatureException {
|
throws SignatureException {
|
||||||
@ -495,9 +516,16 @@ abstract class ECDSASignature extends SignatureSpi {
|
|||||||
@Override
|
@Override
|
||||||
protected void engineSetParameter(AlgorithmParameterSpec params)
|
protected void engineSetParameter(AlgorithmParameterSpec params)
|
||||||
throws InvalidAlgorithmParameterException {
|
throws InvalidAlgorithmParameterException {
|
||||||
if (params != null) {
|
if (params != null && !(params instanceof ECParameterSpec)) {
|
||||||
throw new InvalidAlgorithmParameterException("No parameter accepted");
|
throw new InvalidAlgorithmParameterException("No parameter accepted");
|
||||||
}
|
}
|
||||||
|
ECKey key = (this.privateKey == null? this.publicKey : this.privateKey);
|
||||||
|
if ((key != null) && !isCompatible((ECParameterSpec)params, key.getParams())) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Signature params does not match key params");
|
||||||
|
}
|
||||||
|
|
||||||
|
sigParams = (ECParameterSpec) params;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get parameter, not supported. See JCA doc
|
// get parameter, not supported. See JCA doc
|
||||||
@ -510,7 +538,17 @@ abstract class ECDSASignature extends SignatureSpi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AlgorithmParameters engineGetParameters() {
|
protected AlgorithmParameters engineGetParameters() {
|
||||||
return null;
|
if (sigParams == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
AlgorithmParameters ap = AlgorithmParameters.getInstance("EC");
|
||||||
|
ap.init(sigParams);
|
||||||
|
return ap;
|
||||||
|
} catch (Exception e) {
|
||||||
|
// should never happen
|
||||||
|
throw new ProviderException("Error retrieving EC parameters", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8225745
|
||||||
|
* @summary Ensure ECDSA certificates with signature algorithm parameters
|
||||||
|
* can be verified successfully
|
||||||
|
* @run main ECSigParamsVerifyWithCert
|
||||||
|
*/
|
||||||
|
import java.io.*;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
public class ECSigParamsVerifyWithCert {
|
||||||
|
|
||||||
|
// ECDSA certificate with non-null signature parameters, i.e.
|
||||||
|
// Signature Algorithm: SHA256withECDSA, params unparsed,
|
||||||
|
// OID = 1.2.840.10045.4.3.2
|
||||||
|
private static String ecEntityWithSigParamsStr =
|
||||||
|
"-----BEGIN CERTIFICATE-----\n" +
|
||||||
|
"MIICXjCCAfmgAwIBAgIIHzREzASpiTowFAYIKoZIzj0EAwIGCCqGSM49AwEHMGAx\n" +
|
||||||
|
"IzAhBgNVBAMMGkNvcmRhIE5vZGUgSW50ZXJtZWRpYXRlIENBMQswCQYDVQQKDAJS\n" +
|
||||||
|
"MzEOMAwGA1UECwwFY29yZGExDzANBgNVBAcMBkxvbmRvbjELMAkGA1UEBhMCVUsw\n" +
|
||||||
|
"HhcNMTgwNjI1MDAwMDAwWhcNMjcwNTIwMDAwMDAwWjAxMQswCQYDVQQGEwJHQjEP\n" +
|
||||||
|
"MA0GA1UEBwwGTG9uZG9uMREwDwYDVQQKDAhNZWdhQ29ycDBZMBMGByqGSM49AgEG\n" +
|
||||||
|
"CCqGSM49AwEHA0IABG2VjWPPFnGVka3G9++Sz/GPRkAkht4BDoYTlkRz8hpwr4iu\n" +
|
||||||
|
"fU6NlReirLOB4LBLZcmp16xm4RYsN5ouTS7Z3wKjgcEwgb4wHQYDVR0OBBYEFBnY\n" +
|
||||||
|
"sikYpaSL9U8FUygbqN3sIvMOMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgGG\n" +
|
||||||
|
"MCMGA1UdJQQcMBoGCCsGAQUFBwMBBggrBgEFBQcDAgYEVR0lADARBgorBgEEAYOK\n" +
|
||||||
|
"YgEBBAMCAQQwRwYDVR0eAQH/BD0wO6A3MDWkMzAxMQswCQYDVQQGEwJHQjEPMA0G\n" +
|
||||||
|
"A1UEBwwGTG9uZG9uMREwDwYDVQQKDAhNZWdhQ29ycKEAMBQGCCqGSM49BAMCBggq\n" +
|
||||||
|
"hkjOPQMBBwNJADBGAiEAos+QzgwwH2hfOtrlLncHnoT2YXXHP4q5h01T2DRmjcMC\n" +
|
||||||
|
"IQDa3xZz7CkyyNO1+paAthiNVIlGwwnl4UxuYMwkAiWACw==\n" +
|
||||||
|
"-----END CERTIFICATE-----\n";
|
||||||
|
|
||||||
|
// ECDSA certificate with only signature algorithm oid, no parameters, i.e.
|
||||||
|
// Signature Algorithm: SHA256withECDSA, OID = 1.2.840.10045.4.3.2
|
||||||
|
private static String ecSigner =
|
||||||
|
"-----BEGIN CERTIFICATE-----\n" +
|
||||||
|
"MIICETCCAbigAwIBAgIIaHr3YTnjT8YwCgYIKoZIzj0EAwIwWDEbMBkGA1UEAwwS\n" +
|
||||||
|
"Q29yZGEgTm9kZSBSb290IENBMQswCQYDVQQKDAJSMzEOMAwGA1UECwwFY29yZGEx\n" +
|
||||||
|
"DzANBgNVBAcMBkxvbmRvbjELMAkGA1UEBhMCVUswHhcNMTcwNTIyMDAwMDAwWhcN\n" +
|
||||||
|
"MjcwNTIwMDAwMDAwWjBgMSMwIQYDVQQDDBpDb3JkYSBOb2RlIEludGVybWVkaWF0\n" +
|
||||||
|
"ZSBDQTELMAkGA1UECgwCUjMxDjAMBgNVBAsMBWNvcmRhMQ8wDQYDVQQHDAZMb25k\n" +
|
||||||
|
"b24xCzAJBgNVBAYTAlVLMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEA8veoCbh\n" +
|
||||||
|
"ZmazlyIFWjExBd8ru5OYdFW9Z9ZD5BVg/dswdKC4dlHMHe/sQ4TxFmkYNqf7DTTt\n" +
|
||||||
|
"ePtdHT7Eb1LGYKNkMGIwHQYDVR0OBBYEFOvuLjAVKUCuGZge2G/jfX8HosITMAsG\n" +
|
||||||
|
"A1UdDwQEAwIBhjAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUHAwIGBFUdJQAw\n" +
|
||||||
|
"DwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBEAiB6wr47tuC71qi6+FbY\n" +
|
||||||
|
"XYDTvK+QmAi5ywkFc95I9fPLaQIgIM+nNNQ50NwK610h3bG37XC2tGu+A7Dhtt2Q\n" +
|
||||||
|
"4nDqu30=\n" +
|
||||||
|
"-----END CERTIFICATE-----\n";
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
|
||||||
|
ByteArrayInputStream is
|
||||||
|
= new ByteArrayInputStream(ecEntityWithSigParamsStr.getBytes());
|
||||||
|
X509Certificate ecEntityWithSigParams = (X509Certificate)certFactory.generateCertificate(is);
|
||||||
|
is = new ByteArrayInputStream(ecSigner.getBytes());
|
||||||
|
X509Certificate ecSigner = (X509Certificate)certFactory.generateCertificate(is);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ecEntityWithSigParams.verify(ecSigner.getPublicKey());
|
||||||
|
System.out.println("Test Passed: EC Cert verified");
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Failed, cannot verify EC certificate with sig params");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user