--- a/src/java.base/share/classes/java/security/spec/PSSParameterSpec.java Fri Dec 07 16:56:53 2018 -0800
+++ b/src/java.base/share/classes/java/security/spec/PSSParameterSpec.java Wed Jan 16 11:25:55 2019 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -26,7 +26,6 @@
package java.security.spec;
import java.util.Objects;
-import java.security.spec.MGF1ParameterSpec;
/**
* This class specifies a parameter spec for RSASSA-PSS signature scheme,
@@ -218,4 +217,14 @@
public int getTrailerField() {
return trailerField;
}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("MD: " + mdName + "\n")
+ .append("MGF: " + mgfSpec + "\n")
+ .append("SaltLength: " + saltLen + "\n")
+ .append("TrailerField: " + trailerField + "\n");
+ return sb.toString();
+ }
}
--- a/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java Fri Dec 07 16:56:53 2018 -0800
+++ b/src/java.base/share/classes/sun/security/pkcs10/PKCS10.java Wed Jan 16 11:25:55 2019 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -32,7 +32,6 @@
import java.security.cert.CertificateException;
import java.security.*;
-import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;
@@ -237,10 +236,14 @@
*/
AlgorithmId algId = null;
try {
- algId = AlgorithmId.get(signature.getAlgorithm());
+ AlgorithmParameters params = signature.getParameters();
+ algId = params == null
+ ? AlgorithmId.get(signature.getAlgorithm())
+ : AlgorithmId.get(params);
} catch (NoSuchAlgorithmException nsae) {
throw new SignatureException(nsae);
}
+
algId.encode(scratch); // sig algorithm
scratch.putBitString(sig); // sig
--- a/src/java.base/share/classes/sun/security/rsa/PSSParameters.java Fri Dec 07 16:56:53 2018 -0800
+++ b/src/java.base/share/classes/sun/security/rsa/PSSParameters.java Wed Jan 16 11:25:55 2019 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -52,13 +52,7 @@
public final class PSSParameters extends AlgorithmParametersSpi {
- private String mdName;
- private MGF1ParameterSpec mgfSpec;
- private int saltLength;
- private int trailerField;
-
- private static final ObjectIdentifier OID_MGF1 =
- ObjectIdentifier.newInternal(new int[] {1,2,840,113549,1,1,8});
+ private PSSParameterSpec spec;
public PSSParameters() {
}
@@ -71,9 +65,9 @@
("Inappropriate parameter specification");
}
PSSParameterSpec spec = (PSSParameterSpec) paramSpec;
- this.mdName = spec.getDigestAlgorithm();
+
String mgfName = spec.getMGFAlgorithm();
- if (!mgfName.equalsIgnoreCase("MGF1")) {
+ if (!spec.getMGFAlgorithm().equalsIgnoreCase("MGF1")) {
throw new InvalidParameterSpecException("Unsupported mgf " +
mgfName + "; MGF1 only");
}
@@ -82,31 +76,30 @@
throw new InvalidParameterSpecException("Inappropriate mgf " +
"parameters; non-null MGF1ParameterSpec only");
}
- this.mgfSpec = (MGF1ParameterSpec) mgfSpec;
- this.saltLength = spec.getSaltLength();
- this.trailerField = spec.getTrailerField();
+ this.spec = spec;
}
@Override
protected void engineInit(byte[] encoded) throws IOException {
// first initialize with the DEFAULT values before
// retrieving from the encoding bytes
- this.mdName = DEFAULT.getDigestAlgorithm();
- this.mgfSpec = (MGF1ParameterSpec) DEFAULT.getMGFParameters();
- this.saltLength = DEFAULT.getSaltLength();
- this.trailerField = DEFAULT.getTrailerField();
+ String mdName = DEFAULT.getDigestAlgorithm();
+ MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) DEFAULT.getMGFParameters();
+ int saltLength = DEFAULT.getSaltLength();
+ int trailerField = DEFAULT.getTrailerField();
DerInputStream der = new DerInputStream(encoded);
DerValue[] datum = der.getSequence(4);
+
for (DerValue d : datum) {
if (d.isContextSpecific((byte) 0x00)) {
// hash algid
- this.mdName = AlgorithmId.parse
+ mdName = AlgorithmId.parse
(d.data.getDerValue()).getName();
} else if (d.isContextSpecific((byte) 0x01)) {
// mgf algid
AlgorithmId val = AlgorithmId.parse(d.data.getDerValue());
- if (!val.getOID().equals(OID_MGF1)) {
+ if (!val.getOID().equals(AlgorithmId.mgf1_oid)) {
throw new IOException("Only MGF1 mgf is supported");
}
AlgorithmId params = AlgorithmId.parse(
@@ -114,25 +107,25 @@
String mgfDigestName = params.getName();
switch (mgfDigestName) {
case "SHA-1":
- this.mgfSpec = MGF1ParameterSpec.SHA1;
+ mgfSpec = MGF1ParameterSpec.SHA1;
break;
case "SHA-224":
- this.mgfSpec = MGF1ParameterSpec.SHA224;
+ mgfSpec = MGF1ParameterSpec.SHA224;
break;
case "SHA-256":
- this.mgfSpec = MGF1ParameterSpec.SHA256;
+ mgfSpec = MGF1ParameterSpec.SHA256;
break;
case "SHA-384":
- this.mgfSpec = MGF1ParameterSpec.SHA384;
+ mgfSpec = MGF1ParameterSpec.SHA384;
break;
case "SHA-512":
- this.mgfSpec = MGF1ParameterSpec.SHA512;
+ mgfSpec = MGF1ParameterSpec.SHA512;
break;
case "SHA-512/224":
- this.mgfSpec = MGF1ParameterSpec.SHA512_224;
+ mgfSpec = MGF1ParameterSpec.SHA512_224;
break;
case "SHA-512/256":
- this.mgfSpec = MGF1ParameterSpec.SHA512_256;
+ mgfSpec = MGF1ParameterSpec.SHA512_256;
break;
default:
throw new IOException
@@ -141,21 +134,24 @@
}
} else if (d.isContextSpecific((byte) 0x02)) {
// salt length
- this.saltLength = d.data.getDerValue().getInteger();
- if (this.saltLength < 0) {
+ saltLength = d.data.getDerValue().getInteger();
+ if (saltLength < 0) {
throw new IOException("Negative value for saltLength");
}
} else if (d.isContextSpecific((byte) 0x03)) {
// trailer field
- this.trailerField = d.data.getDerValue().getInteger();
- if (this.trailerField != 1) {
+ trailerField = d.data.getDerValue().getInteger();
+ if (trailerField != 1) {
throw new IOException("Unsupported trailerField value " +
- this.trailerField);
+ trailerField);
}
} else {
throw new IOException("Invalid encoded PSSParameters");
}
}
+
+ this.spec = new PSSParameterSpec(mdName, "MGF1", mgfSpec,
+ saltLength, trailerField);
}
@Override
@@ -173,9 +169,7 @@
T engineGetParameterSpec(Class<T> paramSpec)
throws InvalidParameterSpecException {
if (PSSParameterSpec.class.isAssignableFrom(paramSpec)) {
- return paramSpec.cast(
- new PSSParameterSpec(mdName, "MGF1", mgfSpec,
- saltLength, trailerField));
+ return paramSpec.cast(spec);
} else {
throw new InvalidParameterSpecException
("Inappropriate parameter specification");
@@ -184,54 +178,7 @@
@Override
protected byte[] engineGetEncoded() throws IOException {
- DerOutputStream tmp = new DerOutputStream();
- DerOutputStream tmp2, tmp3;
-
- // MD
- AlgorithmId mdAlgId;
- try {
- mdAlgId = AlgorithmId.get(mdName);
- } catch (NoSuchAlgorithmException nsae) {
- throw new IOException("AlgorithmId " + mdName +
- " impl not found");
- }
- tmp2 = new DerOutputStream();
- mdAlgId.derEncode(tmp2);
- tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0),
- tmp2);
-
- // MGF
- tmp2 = new DerOutputStream();
- tmp2.putOID(OID_MGF1);
- AlgorithmId mgfDigestId;
- try {
- mgfDigestId = AlgorithmId.get(mgfSpec.getDigestAlgorithm());
- } catch (NoSuchAlgorithmException nase) {
- throw new IOException("AlgorithmId " +
- mgfSpec.getDigestAlgorithm() + " impl not found");
- }
- mgfDigestId.encode(tmp2);
- tmp3 = new DerOutputStream();
- tmp3.write(DerValue.tag_Sequence, tmp2);
- tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)1),
- tmp3);
-
- // SaltLength
- tmp2 = new DerOutputStream();
- tmp2.putInteger(saltLength);
- tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)2),
- tmp2);
-
- // TrailerField
- tmp2 = new DerOutputStream();
- tmp2.putInteger(trailerField);
- tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)3),
- tmp2);
-
- // Put all together under a SEQUENCE tag
- DerOutputStream out = new DerOutputStream();
- out.write(DerValue.tag_Sequence, tmp);
- return out.toByteArray();
+ return getEncoded(spec);
}
@Override
@@ -245,11 +192,83 @@
@Override
protected String engineToString() {
- StringBuilder sb = new StringBuilder();
- sb.append("MD: " + mdName + "\n")
- .append("MGF: MGF1" + mgfSpec.getDigestAlgorithm() + "\n")
- .append("SaltLength: " + saltLength + "\n")
- .append("TrailerField: " + trailerField + "\n");
- return sb.toString();
+ return spec.toString();
+ }
+
+ /**
+ * Returns the encoding of a {@link PSSParameterSpec} object. This method
+ * is used in this class and {@link AlgorithmId}.
+ *
+ * @param spec a {@code PSSParameterSpec} object
+ * @return its DER encoding
+ * @throws IOException if the name of a MessageDigest or MaskGenAlgorithm
+ * is unsupported
+ */
+ public static byte[] getEncoded(PSSParameterSpec spec) throws IOException {
+
+ AlgorithmParameterSpec mgfSpec = spec.getMGFParameters();
+ if (!(mgfSpec instanceof MGF1ParameterSpec)) {
+ throw new IOException("Cannot encode " + mgfSpec);
+ }
+
+ MGF1ParameterSpec mgf1Spec = (MGF1ParameterSpec)mgfSpec;
+
+ DerOutputStream tmp = new DerOutputStream();
+ DerOutputStream tmp2, tmp3;
+
+ // MD
+ AlgorithmId mdAlgId;
+ try {
+ mdAlgId = AlgorithmId.get(spec.getDigestAlgorithm());
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new IOException("AlgorithmId " + spec.getDigestAlgorithm() +
+ " impl not found");
+ }
+ if (!mdAlgId.getOID().equals(AlgorithmId.SHA_oid)) {
+ tmp2 = new DerOutputStream();
+ mdAlgId.derEncode(tmp2);
+ tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0),
+ tmp2);
+ }
+
+ // MGF
+ AlgorithmId mgfDigestId;
+ try {
+ mgfDigestId = AlgorithmId.get(mgf1Spec.getDigestAlgorithm());
+ } catch (NoSuchAlgorithmException nase) {
+ throw new IOException("AlgorithmId " +
+ mgf1Spec.getDigestAlgorithm() + " impl not found");
+ }
+
+ if (!mgfDigestId.getOID().equals(AlgorithmId.SHA_oid)) {
+ tmp2 = new DerOutputStream();
+ tmp2.putOID(AlgorithmId.mgf1_oid);
+ mgfDigestId.encode(tmp2);
+ tmp3 = new DerOutputStream();
+ tmp3.write(DerValue.tag_Sequence, tmp2);
+ tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 1),
+ tmp3);
+ }
+
+ // SaltLength
+ if (spec.getSaltLength() != 20) {
+ tmp2 = new DerOutputStream();
+ tmp2.putInteger(spec.getSaltLength());
+ tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 2),
+ tmp2);
+ }
+
+ // TrailerField
+ if (spec.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
+ tmp2 = new DerOutputStream();
+ tmp2.putInteger(spec.getTrailerField());
+ tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 3),
+ tmp2);
+ }
+
+ // Put all together under a SEQUENCE tag
+ DerOutputStream out = new DerOutputStream();
+ out.write(DerValue.tag_Sequence, tmp);
+ return out.toByteArray();
}
}
--- a/src/java.base/share/classes/sun/security/tools/keytool/CertAndKeyGen.java Fri Dec 07 16:56:53 2018 -0800
+++ b/src/java.base/share/classes/sun/security/tools/keytool/CertAndKeyGen.java Wed Jan 16 11:25:55 2019 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -30,6 +30,7 @@
import java.security.cert.CertificateException;
import java.security.cert.CertificateEncodingException;
import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.NamedParameterSpec;
import java.util.Date;
@@ -37,7 +38,6 @@
import sun.security.pkcs10.PKCS10;
import sun.security.x509.*;
-
/**
* Generate a pair of keys, and provide access to them. This class is
* provided primarily for ease of use.
@@ -282,12 +282,14 @@
new CertificateValidity(firstDate,lastDate);
X509CertInfo info = new X509CertInfo();
+ AlgorithmParameterSpec params = AlgorithmId
+ .getDefaultAlgorithmParameterSpec(sigAlg, privateKey);
// Add all mandatory attributes
info.set(X509CertInfo.VERSION,
new CertificateVersion(CertificateVersion.V3));
info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(
new java.util.Random().nextInt() & 0x7fffffff));
- AlgorithmId algID = AlgorithmId.get(sigAlg);
+ AlgorithmId algID = AlgorithmId.getWithParameterSpec(sigAlg, params);
info.set(X509CertInfo.ALGORITHM_ID,
new CertificateAlgorithmId(algID));
info.set(X509CertInfo.SUBJECT, myname);
@@ -297,13 +299,19 @@
if (ext != null) info.set(X509CertInfo.EXTENSIONS, ext);
cert = new X509CertImpl(info);
- cert.sign(privateKey, this.sigAlg);
+ cert.sign(privateKey,
+ params,
+ sigAlg,
+ null);
return (X509Certificate)cert;
} catch (IOException e) {
throw new CertificateEncodingException("getSelfCert: " +
e.getMessage());
+ } catch (InvalidAlgorithmParameterException e2) {
+ throw new SignatureException(
+ "Unsupported PSSParameterSpec: " + e2.getMessage());
}
}
@@ -329,6 +337,7 @@
* @exception InvalidKeyException on key handling errors.
* @exception SignatureException on signature handling errors.
*/
+ // This method is not used inside JDK. Will not update it.
public PKCS10 getCertRequest (X500Name myname)
throws InvalidKeyException, SignatureException
{
--- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java Fri Dec 07 16:56:53 2018 -0800
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java Wed Jan 16 11:25:55 2019 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -52,6 +52,7 @@
import java.security.interfaces.ECKey;
+import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECParameterSpec;
import java.text.Collator;
import java.text.MessageFormat;
@@ -1431,14 +1432,16 @@
signature.initSign(privateKey);
X509CertInfo info = new X509CertInfo();
+ AlgorithmParameterSpec params = AlgorithmId
+ .getDefaultAlgorithmParameterSpec(sigAlgName, privateKey);
+ AlgorithmId algID = AlgorithmId.getWithParameterSpec(sigAlgName, params);
info.set(X509CertInfo.VALIDITY, interval);
info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(
new java.util.Random().nextInt() & 0x7fffffff));
info.set(X509CertInfo.VERSION,
new CertificateVersion(CertificateVersion.V3));
info.set(X509CertInfo.ALGORITHM_ID,
- new CertificateAlgorithmId(
- AlgorithmId.get(sigAlgName)));
+ new CertificateAlgorithmId(algID));
info.set(X509CertInfo.ISSUER, issuer);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
@@ -1482,7 +1485,7 @@
signerCert.getPublicKey());
info.set(X509CertInfo.EXTENSIONS, ext);
X509CertImpl cert = new X509CertImpl(info);
- cert.sign(privateKey, sigAlgName);
+ cert.sign(privateKey, params, sigAlgName, null);
dumpCert(cert, out);
for (Certificate ca: keyStore.getCertificateChain(alias)) {
if (ca instanceof X509Certificate) {
@@ -1585,6 +1588,12 @@
Signature signature = Signature.getInstance(sigAlgName);
signature.initSign(privKey);
+ AlgorithmParameterSpec params = AlgorithmId
+ .getDefaultAlgorithmParameterSpec(sigAlgName, privKey);
+ if (params != null) {
+ signature.setParameter(params);
+ }
+
X500Name subject = dname == null?
new X500Name(((X509Certificate)cert).getSubjectDN().toString()):
new X500Name(dname);
@@ -2962,7 +2971,9 @@
// other solution: We first sign the cert, then retrieve the
// outer sigalg and use it to set the inner sigalg
X509CertImpl newCert = new X509CertImpl(certInfo);
- newCert.sign(privKey, sigAlgName);
+ AlgorithmParameterSpec params = AlgorithmId
+ .getDefaultAlgorithmParameterSpec(sigAlgName, privKey);
+ newCert.sign(privKey, params, sigAlgName, null);
AlgorithmId sigAlgid = (AlgorithmId)newCert.get(X509CertImpl.SIG_ALG);
certInfo.set(CertificateAlgorithmId.NAME + "." +
CertificateAlgorithmId.ALGORITHM, sigAlgid);
@@ -2979,7 +2990,7 @@
certInfo.set(X509CertInfo.EXTENSIONS, ext);
// Sign the new certificate
newCert = new X509CertImpl(certInfo);
- newCert.sign(privKey, sigAlgName);
+ newCert.sign(privKey, params, sigAlgName, null);
// Store the new certificate as a single-element certificate chain
keyStore.setKeyEntry(alias, privKey,
--- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Fri Dec 07 16:56:53 2018 -0800
+++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Wed Jan 16 11:25:55 2019 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -26,9 +26,14 @@
package sun.security.x509;
import java.io.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.PSSParameterSpec;
import java.util.*;
import java.security.*;
+import sun.security.rsa.PSSParameters;
import sun.security.util.*;
@@ -190,7 +195,12 @@
} else {
bytes.putNull();
}*/
- bytes.putNull();
+ if (algid.equals(RSASSA_PSS_oid)) {
+ // RFC 4055 3.3: when an RSASSA-PSS key does not require
+ // parameter validation, field is absent.
+ } else {
+ bytes.putNull();
+ }
} else {
bytes.putDerValue(params);
}
@@ -689,6 +699,8 @@
oid(1, 2, 840, 113549, 1, 1, 1);
public static final ObjectIdentifier RSAES_OAEP_oid =
oid(1, 2, 840, 113549, 1, 1, 7);
+ public static final ObjectIdentifier mgf1_oid =
+ oid(1, 2, 840, 113549, 1, 1, 8);
public static final ObjectIdentifier RSASSA_PSS_oid =
oid(1, 2, 840, 113549, 1, 1, 10);
@@ -1063,6 +1075,81 @@
}
}
+ // Most commonly used PSSParameterSpec and AlgorithmId
+ private static class PSSParamsHolder {
+
+ final static PSSParameterSpec PSS_256_SPEC = new PSSParameterSpec(
+ "SHA-256", "MGF1",
+ new MGF1ParameterSpec("SHA-256"),
+ 32, PSSParameterSpec.TRAILER_FIELD_BC);
+ final static PSSParameterSpec PSS_384_SPEC = new PSSParameterSpec(
+ "SHA-384", "MGF1",
+ new MGF1ParameterSpec("SHA-384"),
+ 48, PSSParameterSpec.TRAILER_FIELD_BC);
+ final static PSSParameterSpec PSS_512_SPEC = new PSSParameterSpec(
+ "SHA-512", "MGF1",
+ new MGF1ParameterSpec("SHA-512"),
+ 64, PSSParameterSpec.TRAILER_FIELD_BC);
+
+ final static AlgorithmId PSS_256_ID;
+ final static AlgorithmId PSS_384_ID;
+ final static AlgorithmId PSS_512_ID;
+
+ static {
+ try {
+ PSS_256_ID = new AlgorithmId(RSASSA_PSS_oid,
+ new DerValue(PSSParameters.getEncoded(PSS_256_SPEC)));
+ PSS_384_ID = new AlgorithmId(RSASSA_PSS_oid,
+ new DerValue(PSSParameters.getEncoded(PSS_384_SPEC)));
+ PSS_512_ID = new AlgorithmId(RSASSA_PSS_oid,
+ new DerValue(PSSParameters.getEncoded(PSS_512_SPEC)));
+ } catch (IOException e) {
+ throw new AssertionError("Should not happen", e);
+ }
+ }
+ }
+
+ public static AlgorithmId getWithParameterSpec(String algName,
+ AlgorithmParameterSpec spec) throws NoSuchAlgorithmException {
+
+ if (spec == null) {
+ return AlgorithmId.get(algName);
+ } else if (spec == PSSParamsHolder.PSS_256_SPEC) {
+ return PSSParamsHolder.PSS_256_ID;
+ } else if (spec == PSSParamsHolder.PSS_384_SPEC) {
+ return PSSParamsHolder.PSS_384_ID;
+ } else if (spec == PSSParamsHolder.PSS_512_SPEC) {
+ return PSSParamsHolder.PSS_512_ID;
+ } else {
+ try {
+ AlgorithmParameters result =
+ AlgorithmParameters.getInstance(algName);
+ result.init(spec);
+ return get(result);
+ } catch (InvalidParameterSpecException | NoSuchAlgorithmException e) {
+ throw new ProviderException(e);
+ }
+ }
+ }
+
+ public static PSSParameterSpec getDefaultAlgorithmParameterSpec(
+ String sigAlg, PrivateKey k) {
+ if (sigAlg.equalsIgnoreCase("RSASSA-PSS")) {
+ switch (ifcFfcStrength(KeyUtil.getKeySize(k))) {
+ case "SHA256":
+ return PSSParamsHolder.PSS_256_SPEC;
+ case "SHA384":
+ return PSSParamsHolder.PSS_384_SPEC;
+ case "SHA512":
+ return PSSParamsHolder.PSS_512_SPEC;
+ default:
+ throw new AssertionError("Should not happen");
+ }
+ } else {
+ return null;
+ }
+ }
+
// Values from SP800-57 part 1 rev 4 tables 2 and 3
private static String ecStrength (int bitLength) {
if (bitLength >= 512) { // 256 bits of strength
--- a/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Fri Dec 07 16:56:53 2018 -0800
+++ b/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Wed Jan 16 11:25:55 2019 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -42,7 +42,6 @@
import javax.security.auth.x500.X500Principal;
-import java.util.Base64;
import sun.security.util.*;
import sun.security.provider.X509Factory;
@@ -599,14 +598,10 @@
sigEngine.initSign(key);
- // set parameters after Signature.initSign/initVerify call, so
- // the deferred provider selection happens when the key is set
- try {
+ if (signingParams != null) {
+ // set parameters after Signature.initSign/initVerify call, so
+ // the deferred provider selection happens when the key is set
sigEngine.setParameter(signingParams);
- } catch (UnsupportedOperationException e) {
- // for backward compatibility, only re-throw when
- // parameters is not null
- if (signingParams != null) throw e;
}
// in case the name is reset
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/tools/keytool/PSS.java Wed Jan 16 11:25:55 2019 +0800
@@ -0,0 +1,108 @@
+/*
+ * 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 8215694
+ * @summary keytool cannot generate RSASSA-PSS certificates
+ * @library /test/lib
+ * @modules java.base/sun.security.util
+ * java.base/sun.security.x509
+ * @run main PSS
+ */
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.SecurityTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.security.DerUtils;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
+
+import java.io.File;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+
+public class PSS {
+
+ public static void main(String[] args) throws Exception {
+
+ genkeypair("p", "-keyalg RSASSA-PSS -sigalg RSASSA-PSS")
+ .shouldHaveExitValue(0);
+
+ genkeypair("a", "-keyalg RSA -sigalg RSASSA-PSS -keysize 2048")
+ .shouldHaveExitValue(0);
+
+ genkeypair("b", "-keyalg RSA -sigalg RSASSA-PSS -keysize 4096")
+ .shouldHaveExitValue(0);
+
+ genkeypair("c", "-keyalg RSA -sigalg RSASSA-PSS -keysize 8192")
+ .shouldHaveExitValue(0);
+
+ KeyStore ks = KeyStore.getInstance(
+ new File("ks"), "changeit".toCharArray());
+
+ check((X509Certificate)ks.getCertificate("p"), "RSASSA-PSS",
+ AlgorithmId.SHA256_oid);
+
+ check((X509Certificate)ks.getCertificate("a"), "RSA",
+ AlgorithmId.SHA256_oid);
+
+ check((X509Certificate)ks.getCertificate("b"), "RSA",
+ AlgorithmId.SHA384_oid);
+
+ check((X509Certificate)ks.getCertificate("c"), "RSA",
+ AlgorithmId.SHA512_oid);
+
+ // More commands
+ kt("-certreq -alias p -sigalg RSASSA-PSS -file p.req")
+ .shouldHaveExitValue(0);
+
+ kt("-gencert -alias a -sigalg RSASSA-PSS -infile p.req -outfile p.cert")
+ .shouldHaveExitValue(0);
+
+ kt("-importcert -alias p -file p.cert")
+ .shouldHaveExitValue(0);
+
+ kt("-selfcert -alias p -sigalg RSASSA-PSS")
+ .shouldHaveExitValue(0);
+ }
+
+ static OutputAnalyzer genkeypair(String alias, String options)
+ throws Exception {
+ return kt("-genkeypair -alias " + alias
+ + " -dname CN=" + alias + " " + options);
+ }
+
+ static OutputAnalyzer kt(String cmd)
+ throws Exception {
+ return SecurityTools.keytool("-storepass changeit -keypass changeit "
+ + "-keystore ks " + cmd);
+ }
+
+ static void check(X509Certificate cert, String expectedKeyAlg,
+ ObjectIdentifier expectedMdAlg) throws Exception {
+ Asserts.assertEQ(cert.getPublicKey().getAlgorithm(), expectedKeyAlg);
+ Asserts.assertEQ(cert.getSigAlgName(), "RSASSA-PSS");
+ DerUtils.checkAlg(cert.getSigAlgParams(), "000", expectedMdAlg);
+ }
+}