-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8325766: Review seclibs tests for cert expiry #23700
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
👋 Welcome back mdonovan! A progress list of the required criteria for merging this PR into |
❗ This change is not yet ready to be integrated. |
throws CertificateException, IOException { | ||
SecureRandom random = new SecureRandom(); | ||
|
||
boolean [] keyUsage = new boolean[]{false, false, false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be easier to just use var keyUsage = new boolean[KeyUsage.values().length]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the array initialization.
test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java
Show resolved
Hide resolved
The similarity between the certificate pairs is impressive! Just curious - why the change in issuer and owner names? |
Looks like it's something between |
After looking into this some more, I found that OpenSSL prints them backwards and I was using OpenSSL to print the hard-coded certificates and then just copying and pasting the strings. I changed the hard-coded DN strings to follow the RFC order. |
KeyUsage.DIGITAL_SIGNATURE, KeyUsage.NONREPUDIATION, KeyUsage.KEY_ENCIPHERMENT) | ||
.addBasicConstraintsExt(false, false, -1) | ||
.addExtension(CertificateBuilder.createIPSubjectAltNameExt(true, "127.0.0.1")) | ||
.build(trustedCert, caKeys.getPrivate(), "MD5WithRSA"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MD5 algorithm is not allowed in TLSv1.3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll address this in JDK-8353738
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, thanks!
test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPIdentities.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@mpdonova This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply issue a |
public static CertificateBuilder newCertificateBuilder(String subjectName, | ||
PublicKey publicKey, PublicKey caKey, KeyUsage... keyUsages) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suggestion is to make this a regular constructor and have an additional method that sets the certificate lifetime as a Duration
parameter, ex:
new CertificateBuilder(subject, pubKey, caPubKey, keyUsage).withValidity(Duration.ofHours(1));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the way it currently is follows the builder pattern better. All of the 'set' methods return this
which means if I change this method to a constructor, I'd have to duplicate the "set" code from all those methods.
I like the idea of using Duration
but the API for it doesn't really lend itself to this use case. When the certificate is finally created, we write Date
objects to the DerOutputStream so I'd have to choose a start time and then calculate the end time based on the duration. It's not hard, but it doesn't seem worth it when the common use case of this class is to generate short-lived certificates for a test. The default one-hour validity will cover the vast majority of tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the way it currently is follows the builder pattern better. All of the 'set' methods return
this
which means if I change this method to a constructor, I'd have to duplicate the "set" code from all those methods.
I'm not sure what you mean - can you give an example? I don't see any advantages of using a static method here, but I agree it works either way.
I like the idea of using
Duration
but the API for it doesn't really lend itself to this use case. When the certificate is finally created, we writeDate
objects to the DerOutputStream so I'd have to choose a start time and then calculate the end time based on the duration. It's not hard, but it doesn't seem worth it when the common use case of this class is to generate short-lived certificates for a test. The default one-hour validity will cover the vast majority of tests.
I view this test utility class as being flexible enough for different cases. This is a useful method in that the other parameters are common fields that all certs usually have but it also means I can't use this method to to create a certificate with a longer, or shorter validity period. Alternatively, how about adding another method that hard-codes it as one hour:
CertificateBuilder oneHourValidity()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a constructor, the code would look like this
public CertificateBuilder(String subjectName,
PublicKey publicKey, PublicKey caKey, KeyUsage... keyUsages)
throws CertificateException, IOException {
factory = CertificateFactory.getInstance("X.509");
SecureRandom random = new SecureRandom();
boolean [] keyUsage = new boolean[KeyUsage.values().length];
for (KeyUsage ku : keyUsages) {
keyUsage[ku.ordinal()] = true;
}
this.subjectName = new X500Principal(subjectName);
this.publicKey = Objects.requireNonNull(publicKey, "Caught null public key");
notBefore = (Date)Date.from(Instant.now().minus(1, ChronoUnit.HOURS));
notAfter = Date.from(Instant.now().plus(1, ChronoUnit.HOURS));
serialNumber = BigInteger.valueOf(random.nextLong(1000000)+1);
byte[] keyIdBytes = new KeyIdentifier(publicKey).getIdentifier();
Extension e = new SubjectKeyIdentifierExtension(keyIdBytes);
extensions.put(e.getId(), e);
KeyIdentifier kid = new KeyIdentifier(caKey);
e = new AuthorityKeyIdentifierExtension(kid, null, null);
extensions.put(e.getId(), e);
if (keyUsages.length != 0) {
e = new KeyUsageExtension(keyUsage);
extensions.put(e.getId(), e);
}
}
it also means I can't use this method to to create a certificate with a longer, or shorter validity period
There are methods to set the not-before and not-after fields. Any field set in this static method can be changed:
newCertificateBuilder(...).notAfter(Date.from(Instant.now().plus(10, TimeUnit.YEARS)));
I don't like using Date
here and would be happy to overload it to take Instant
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a constructor, the code would look like this
Ah, I see. Well technically you could call the set methods from the ctor but you would get this-escape
compiler warnings, which you probably want to avoid.
it also means I can't use this method to to create a certificate with a longer, or shorter validity period
There are methods to set the not-before and not-after fields. Any field set in this static method can be changed:
newCertificateBuilder(...).notAfter(Date.from(Instant.now().plus(10, TimeUnit.YEARS)));
I don't like using
Date
here and would be happy to overload it to takeInstant
as well.
Yes, but I don't think the static method which is generically named newCertificateBuilder
should be hard-coding a one hour validity period, that detail should be either in a different method (my preference) or this method should be named more clearly like oneHourCertificateBuilder
. I realize this is just a test method, but this is a nicely designed API that has been very useful so I would prefer if we keep the flexibility.
|
||
private static void setupCertificates() throws Exception { | ||
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); | ||
kpg.initialize(1024); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line can be removed so implementation uses a default value.
Certificate trusedCert = cf.generateCertificate(is); | ||
is.close(); | ||
private static SSLContext getSSLContext(X509Certificate trustedCert, | ||
X509Certificate keyCert, KeyPair key, char[] passphrase) throws Exception { | ||
|
||
// create a key store | ||
KeyStore ks = KeyStore.getInstance("JKS"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest changing a key store type to PKCS12
, should be a better choice in the long run.
This PR updates the CertificateBuilder with a new method that creates a new instance with common fields (subject name, public key, serial number, validity, and key uses) filled-in. One test, IPIdentities.java, is updated to show how the method can be used to create various certificates. I attached screenshots that compare the old hard-coded certificates (left) with the new generated certificates.
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/23700/head:pull/23700
$ git checkout pull/23700
Update a local copy of the PR:
$ git checkout pull/23700
$ git pull https://git.openjdk.org/jdk.git pull/23700/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 23700
View PR using the GUI difftool:
$ git pr show -t 23700
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/23700.diff
Using Webrev
Link to Webrev Comment