8172366: Support SHA-3 based signatures

Enhance default JDK providers including SUN, SunRsaSign, and SunEC, with signatures using SHA-3 family of digests.

Reviewed-by: xuelei
This commit is contained in:
Valerie Peng 2020-09-15 20:28:48 +00:00
parent 46598c8644
commit 40206822f4
20 changed files with 673 additions and 95 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, 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
@ -103,7 +103,7 @@ public final class PSSParameters extends AlgorithmParametersSpi {
throw new IOException("Only MGF1 mgf is supported");
}
AlgorithmId params = AlgorithmId.parse(
new DerValue(val.getEncodedParams()));
new DerValue(val.getEncodedParams()));
String mgfDigestName = params.getName();
switch (mgfDigestName) {
case "SHA-1":
@ -127,6 +127,18 @@ public final class PSSParameters extends AlgorithmParametersSpi {
case "SHA-512/256":
mgfSpec = MGF1ParameterSpec.SHA512_256;
break;
case "SHA3-224":
mgfSpec = MGF1ParameterSpec.SHA3_224;
break;
case "SHA3-256":
mgfSpec = MGF1ParameterSpec.SHA3_256;
break;
case "SHA3-384":
mgfSpec = MGF1ParameterSpec.SHA3_384;
break;
case "SHA3-512":
mgfSpec = MGF1ParameterSpec.SHA3_512;
break;
default:
throw new IOException
("Unrecognized message digest algorithm " +

View file

@ -45,8 +45,8 @@ import sun.security.jca.JCAUtil;
* PKCS#1 v2.2 RSASSA-PSS signatures with various message digest algorithms.
* RSASSA-PSS implementation takes the message digest algorithm, MGF algorithm,
* and salt length values through the required signature PSS parameters.
* We support SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and
* SHA-512/256 message digest algorithms and MGF1 mask generation function.
* We support SHA-1, SHA-2 family and SHA3 family of message digest algorithms,
* and MGF1 mask generation function.
*
* @since 11
*/
@ -81,24 +81,20 @@ public class RSAPSSSignature extends SignatureSpi {
private static final byte[] EIGHT_BYTES_OF_ZEROS = new byte[8];
private static final Hashtable<String, Integer> DIGEST_LENGTHS =
new Hashtable<String, Integer>();
private static final Hashtable<KnownOIDs, Integer> DIGEST_LENGTHS =
new Hashtable<KnownOIDs, Integer>();
static {
DIGEST_LENGTHS.put("SHA-1", 20);
DIGEST_LENGTHS.put("SHA", 20);
DIGEST_LENGTHS.put("SHA1", 20);
DIGEST_LENGTHS.put("SHA-224", 28);
DIGEST_LENGTHS.put("SHA224", 28);
DIGEST_LENGTHS.put("SHA-256", 32);
DIGEST_LENGTHS.put("SHA256", 32);
DIGEST_LENGTHS.put("SHA-384", 48);
DIGEST_LENGTHS.put("SHA384", 48);
DIGEST_LENGTHS.put("SHA-512", 64);
DIGEST_LENGTHS.put("SHA512", 64);
DIGEST_LENGTHS.put("SHA-512/224", 28);
DIGEST_LENGTHS.put("SHA512/224", 28);
DIGEST_LENGTHS.put("SHA-512/256", 32);
DIGEST_LENGTHS.put("SHA512/256", 32);
DIGEST_LENGTHS.put(KnownOIDs.SHA_1, 20);
DIGEST_LENGTHS.put(KnownOIDs.SHA_224, 28);
DIGEST_LENGTHS.put(KnownOIDs.SHA_256, 32);
DIGEST_LENGTHS.put(KnownOIDs.SHA_384, 48);
DIGEST_LENGTHS.put(KnownOIDs.SHA_512, 64);
DIGEST_LENGTHS.put(KnownOIDs.SHA_512$224, 28);
DIGEST_LENGTHS.put(KnownOIDs.SHA_512$256, 32);
DIGEST_LENGTHS.put(KnownOIDs.SHA3_224, 28);
DIGEST_LENGTHS.put(KnownOIDs.SHA3_256, 32);
DIGEST_LENGTHS.put(KnownOIDs.SHA3_384, 48);
DIGEST_LENGTHS.put(KnownOIDs.SHA3_512, 64);
}
// message digest implementation we use for hashing the data
@ -210,27 +206,33 @@ public class RSAPSSSignature extends SignatureSpi {
* internal signature parameters.
*/
private RSAKey isValid(RSAKey rsaKey) throws InvalidKeyException {
try {
AlgorithmParameterSpec keyParams = rsaKey.getParams();
// validate key parameters
if (!isCompatible(rsaKey.getParams(), this.sigParams)) {
throw new InvalidKeyException
("Key contains incompatible PSS parameter values");
}
// validate key length
if (this.sigParams != null) {
Integer hLen =
DIGEST_LENGTHS.get(this.sigParams.getDigestAlgorithm());
if (hLen == null) {
throw new ProviderException("Unsupported digest algo: " +
this.sigParams.getDigestAlgorithm());
}
checkKeyLength(rsaKey, hLen, this.sigParams.getSaltLength());
}
return rsaKey;
} catch (SignatureException e) {
throw new InvalidKeyException(e);
AlgorithmParameterSpec keyParams = rsaKey.getParams();
// validate key parameters
if (!isCompatible(rsaKey.getParams(), this.sigParams)) {
throw new InvalidKeyException
("Key contains incompatible PSS parameter values");
}
// validate key length
if (this.sigParams != null) {
String digestAlgo = this.sigParams.getDigestAlgorithm();
KnownOIDs ko = KnownOIDs.findMatch(digestAlgo);
if (ko != null) {
Integer hLen = DIGEST_LENGTHS.get(ko);
if (hLen != null) {
checkKeyLength(rsaKey, hLen,
this.sigParams.getSaltLength());
} else {
// should never happen; checked in validateSigParams()
throw new ProviderException
("Unsupported digest algo: " + digestAlgo);
}
} else {
// should never happen; checked in validateSigParams()
throw new ProviderException
("Unrecognized digest algo: " + digestAlgo);
}
}
return rsaKey;
}
/**
@ -268,14 +270,26 @@ public class RSAPSSSignature extends SignatureSpi {
("Only supports TrailerFieldBC(1)");
}
String digestAlgo = params.getDigestAlgorithm();
// check key length again
if (key != null) {
try {
int hLen = DIGEST_LENGTHS.get(digestAlgo);
checkKeyLength(key, hLen, params.getSaltLength());
} catch (SignatureException e) {
throw new InvalidAlgorithmParameterException(e);
String digestAlgo = params.getDigestAlgorithm();
KnownOIDs ko = KnownOIDs.findMatch(digestAlgo);
if (ko != null) {
Integer hLen = DIGEST_LENGTHS.get(ko);
if (hLen != null) {
try {
checkKeyLength(key, hLen, params.getSaltLength());
} catch (InvalidKeyException e) {
throw new InvalidAlgorithmParameterException(e);
}
} else {
throw new InvalidAlgorithmParameterException
("Unsupported digest algo: " + digestAlgo);
}
} else {
throw new InvalidAlgorithmParameterException
("Unrecognized digest algo: " + digestAlgo);
}
}
return params;
@ -302,12 +316,12 @@ public class RSAPSSSignature extends SignatureSpi {
* salt length
*/
private static void checkKeyLength(RSAKey key, int digestLen,
int saltLen) throws SignatureException {
int saltLen) throws InvalidKeyException {
if (key != null) {
int keyLength = (getKeyLengthInBits(key) + 7) >> 3;
int minLength = Math.addExact(Math.addExact(digestLen, saltLen), 2);
if (keyLength < minLength) {
throw new SignatureException
throw new InvalidKeyException
("Key is too short, need min " + minLength + " bytes");
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, 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
@ -40,8 +40,9 @@ import sun.security.x509.AlgorithmId;
* PKCS#1 v1.5 RSA signatures with the various message digest algorithms.
* This file contains an abstract base class with all the logic plus
* a nested static class for each of the message digest algorithms
* (see end of the file). We support MD2, MD5, SHA-1, SHA-224, SHA-256,
* SHA-384, SHA-512, SHA-512/224, and SHA-512/256.
* (see end of the file). We support MD2, MD5, SHA-1, SHA2 family (
* SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256),
* and SHA3 family (SHA3-224, SHA3-256, SHA3-384, SHA3-512) of digests.
*
* @since 1.5
* @author Andreas Sterbenz
@ -360,4 +361,32 @@ public abstract class RSASignature extends SignatureSpi {
super("SHA-512/256", AlgorithmId.SHA512_256_oid, 11);
}
}
// Nested class for SHA3-224withRSA signatures
public static final class SHA3_224withRSA extends RSASignature {
public SHA3_224withRSA() {
super("SHA3-224", AlgorithmId.SHA3_224_oid, 11);
}
}
// Nested class for SHA3-256withRSA signatures
public static final class SHA3_256withRSA extends RSASignature {
public SHA3_256withRSA() {
super("SHA3-256", AlgorithmId.SHA3_256_oid, 11);
}
}
// Nested class for SHA3-384withRSA signatures
public static final class SHA3_384withRSA extends RSASignature {
public SHA3_384withRSA() {
super("SHA3-384", AlgorithmId.SHA3_384_oid, 11);
}
}
// Nested class for SHA3-512withRSA signatures
public static final class SHA3_512withRSA extends RSASignature {
public SHA3_512withRSA() {
super("SHA3-512", AlgorithmId.SHA3_512_oid, 11);
}
}
}

View file

@ -84,6 +84,14 @@ public final class SunRsaSignEntries {
"sun.security.rsa.RSASignature$SHA512_224withRSA", attrs);
addA(p, "Signature", "SHA512/256withRSA",
"sun.security.rsa.RSASignature$SHA512_256withRSA", attrs);
addA(p, "Signature", "SHA3-224withRSA",
"sun.security.rsa.RSASignature$SHA3_224withRSA", attrs);
addA(p, "Signature", "SHA3-256withRSA",
"sun.security.rsa.RSASignature$SHA3_256withRSA", attrs);
addA(p, "Signature", "SHA3-384withRSA",
"sun.security.rsa.RSASignature$SHA3_384withRSA", attrs);
addA(p, "Signature", "SHA3-512withRSA",
"sun.security.rsa.RSASignature$SHA3_512withRSA", attrs);
addA(p, "KeyFactory", "RSASSA-PSS",
"sun.security.rsa.RSAKeyFactory$PSS", attrs);
@ -92,7 +100,7 @@ public final class SunRsaSignEntries {
addA(p, "Signature", "RSASSA-PSS",
"sun.security.rsa.RSAPSSSignature", attrs);
addA(p, "AlgorithmParameters", "RSASSA-PSS",
"sun.security.rsa.PSSParameters", attrs);
"sun.security.rsa.PSSParameters", null);
}
public Iterator<Provider.Service> iterator() {