Remove java.util.Date (#2373)

There is one remaining instance in JpaTransactionManagerImpl that cannot
be removed because DetachingTypedQuery is implementing TypedQuery, which has
a method that expectred java.util.Date.
This commit is contained in:
Lai Jiang 2024-03-15 19:06:00 -04:00 committed by GitHub
parent 6d2eb2e140
commit c68583f666
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 108 additions and 147 deletions

View file

@ -173,17 +173,24 @@ PRESUBMITS = {
): ):
"JavaScript files should not include console logging.", "JavaScript files should not include console logging.",
PresubmitCheck( PresubmitCheck(
r"org\.testcontainers\.shaded\.", r".*org\.testcontainers\.shaded.*",
"java", "java",
{"/node_modules/"}, {"/node_modules/"},
): ):
"Do not use shaded dependencies from testcontainers.", "Do not use shaded dependencies from testcontainers.",
PresubmitCheck( PresubmitCheck(
r"com\.google\.common\.truth\.Truth8", r".*com\.google\.common\.truth\.Truth8.*",
"java", "java",
{"/node_modules/"}, {"/node_modules/"},
): ):
"Truth8 is deprecated. Use Truth instead.", "Truth8 is deprecated. Use Truth instead.",
PresubmitCheck(
r".*java\.util\.Date.*",
"java",
{"/node_modules/", "JpaTransactionManagerImpl.java"},
):
"Do not use java.util.Date. Use classes in java.time package instead.",
} }
# Note that this regex only works for one kind of Flyway file. If we want to # Note that this regex only works for one kind of Flyway file. If we want to

View file

@ -45,7 +45,6 @@ import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.Duration; import java.time.Duration;
import java.util.Collection; import java.util.Collection;
import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
@ -195,10 +194,7 @@ public class DelegatedCredentials extends GoogleCredentials {
GenericData responseData = response.parseAs(GenericData.class); GenericData responseData = response.parseAs(GenericData.class);
String accessToken = validateString(responseData, "access_token", PARSE_ERROR_PREFIX); String accessToken = validateString(responseData, "access_token", PARSE_ERROR_PREFIX);
int expiresInSeconds = validateInt32(responseData, "expires_in", PARSE_ERROR_PREFIX); int expiresInSeconds = validateInt32(responseData, "expires_in", PARSE_ERROR_PREFIX);
long expiresAtMilliseconds = clock.nowUtc().getMillis() + expiresInSeconds * 1000L; return new AccessToken(accessToken, clock.nowUtc().plusSeconds(expiresInSeconds).toDate());
@SuppressWarnings("JavaUtilDate")
AccessToken token = new AccessToken(accessToken, new Date(expiresAtMilliseconds));
return token;
} }
String createAssertion(JsonFactory jsonFactory, long currentTime) throws IOException { String createAssertion(JsonFactory jsonFactory, long currentTime) throws IOException {
@ -257,8 +253,7 @@ public class DelegatedCredentials extends GoogleCredentials {
if (value == null) { if (value == null) {
throw new IOException(String.format(VALUE_NOT_FOUND_MESSAGE, errorPrefix, key)); throw new IOException(String.format(VALUE_NOT_FOUND_MESSAGE, errorPrefix, key));
} }
if (value instanceof BigDecimal) { if (value instanceof BigDecimal bigDecimalValue) {
BigDecimal bigDecimalValue = (BigDecimal) value;
return bigDecimalValue.intValueExact(); return bigDecimalValue.intValueExact();
} }
if (!(value instanceof Integer)) { if (!(value instanceof Integer)) {

View file

@ -31,7 +31,6 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.security.interfaces.ECPublicKey; import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.util.Date;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.inject.Inject; import javax.inject.Inject;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
@ -106,12 +105,9 @@ public class CertificateChecker {
// These 2 different instances of PublicKey need to be handled separately since their OIDs are // These 2 different instances of PublicKey need to be handled separately since their OIDs are
// encoded differently. More details on this can be found at // encoded differently. More details on this can be found at
// https://stackoverflow.com/questions/49895713/how-to-find-the-matching-curve-name-from-an-ecpublickey. // https://stackoverflow.com/questions/49895713/how-to-find-the-matching-curve-name-from-an-ecpublickey.
if (key instanceof ECPublicKey) { if (key instanceof ECPublicKey ecKey) {
ECPublicKey ecKey = (ECPublicKey) key;
params = EC5Util.convertSpec(ecKey.getParams()); params = EC5Util.convertSpec(ecKey.getParams());
} else if (key instanceof org.bouncycastle.jce.interfaces.ECPublicKey) { } else if (key instanceof org.bouncycastle.jce.interfaces.ECPublicKey ecKey) {
org.bouncycastle.jce.interfaces.ECPublicKey ecKey =
(org.bouncycastle.jce.interfaces.ECPublicKey) key;
params = ecKey.getParameters(); params = ecKey.getParameters();
} else { } else {
throw new IllegalArgumentException("Unrecognized instance of PublicKey."); throw new IllegalArgumentException("Unrecognized instance of PublicKey.");
@ -148,7 +144,7 @@ public class CertificateChecker {
if (!violations.isEmpty()) { if (!violations.isEmpty()) {
String displayMessages = String displayMessages =
violations.stream() violations.stream()
.map(violation -> getViolationDisplayMessage(violation)) .map(this::getViolationDisplayMessage)
.collect(Collectors.joining("\n")); .collect(Collectors.joining("\n"));
throw new InsecureCertificateException(violations, displayMessages); throw new InsecureCertificateException(violations, displayMessages);
} }
@ -162,7 +158,7 @@ public class CertificateChecker {
ImmutableSet.Builder<CertificateViolation> violations = new ImmutableSet.Builder<>(); ImmutableSet.Builder<CertificateViolation> violations = new ImmutableSet.Builder<>();
// Check if currently in validity period // Check if currently in validity period
Date now = clock.nowUtc().toDate(); DateTime now = clock.nowUtc();
if (DateTimeComparator.getInstance().compare(certificate.getNotAfter(), now) < 0) { if (DateTimeComparator.getInstance().compare(certificate.getNotAfter(), now) < 0) {
violations.add(CertificateViolation.EXPIRED); violations.add(CertificateViolation.EXPIRED);
} else if (DateTimeComparator.getInstance().compare(certificate.getNotBefore(), now) > 0) { } else if (DateTimeComparator.getInstance().compare(certificate.getNotBefore(), now) > 0) {
@ -231,13 +227,13 @@ public class CertificateChecker {
DateTime lastExpiringNotificationSentDate, String certificateStr) { DateTime lastExpiringNotificationSentDate, String certificateStr) {
X509Certificate certificate = getCertificate(certificateStr); X509Certificate certificate = getCertificate(certificateStr);
DateTime now = clock.nowUtc(); DateTime now = clock.nowUtc();
// expiration date is one day after lastValidDate // the expiration date is one day after lastValidDate
DateTime lastValidDate = new DateTime(certificate.getNotAfter()); DateTime lastValidDate = new DateTime(certificate.getNotAfter());
if (lastValidDate.isBefore(now)) { if (lastValidDate.isBefore(now)) {
return false; return false;
} }
/* /*
* Client should receive a notification if : * Client should receive a notification if:
* 1) client has never received notification (lastExpiringNotificationSentDate is initially * 1) client has never received notification (lastExpiringNotificationSentDate is initially
* set to START_OF_TIME) and the certificate has entered the expiring period, OR * set to START_OF_TIME) and the certificate has entered the expiring period, OR
* 2) client has received notification but the interval between now and * 2) client has received notification but the interval between now and
@ -254,29 +250,21 @@ public class CertificateChecker {
// Yes, we'd rather do this as an instance method on the CertificateViolation enum itself, but // Yes, we'd rather do this as an instance method on the CertificateViolation enum itself, but
// we can't because we need access to configuration (injected as instance variables) which you // we can't because we need access to configuration (injected as instance variables) which you
// can't get in a static enum context. // can't get in a static enum context.
switch (certificateViolation) { return switch (certificateViolation) {
case EXPIRED: case EXPIRED -> "Certificate is expired.";
return "Certificate is expired."; case NOT_YET_VALID -> "Certificate start date is in the future.";
case NOT_YET_VALID: case ALGORITHM_CONSTRAINED -> "Certificate key algorithm must be RSA or ECDSA.";
return "Certificate start date is in the future."; case RSA_KEY_LENGTH_TOO_SHORT ->
case ALGORITHM_CONSTRAINED: String.format(
return "Certificate key algorithm must be RSA or ECDSA."; "RSA key length is too short; the minimum allowed length is %d bits.",
case RSA_KEY_LENGTH_TOO_SHORT: this.minimumRsaKeyLength);
return String.format( case VALIDITY_LENGTH_TOO_LONG ->
"RSA key length is too short; the minimum allowed length is %d bits.", String.format(
this.minimumRsaKeyLength); "Certificate validity period is too long; it must be less than or equal to %d days.",
case VALIDITY_LENGTH_TOO_LONG: this.maxValidityLengthSchedule.lastEntry().getValue());
return String.format( case INVALID_ECDSA_CURVE ->
"Certificate validity period is too long; it must be less than or equal to %d days.", String.format("The ECDSA key must use one of these algorithms: %s", allowedEcdsaCurves);
this.maxValidityLengthSchedule.lastEntry().getValue()); };
case INVALID_ECDSA_CURVE:
return String.format(
"The ECDSA key must use one of these algorithms: %s", allowedEcdsaCurves);
default:
throw new IllegalArgumentException(
String.format(
"Unknown CertificateViolation enum value: %s", certificateViolation.name()));
}
} }
/** /**
@ -295,7 +283,7 @@ public class CertificateChecker {
* Gets a suitable end-user-facing display message for this particular certificate violation. * Gets a suitable end-user-facing display message for this particular certificate violation.
* *
* <p>Note that the {@link CertificateChecker} instance must be passed in because it contains * <p>Note that the {@link CertificateChecker} instance must be passed in because it contains
* configuration values (e.g. minimum RSA key length) that go into the error message text. * configuration values (e.g., minimum RSA key length) that go into the error message text.
*/ */
public String getDisplayMessage(CertificateChecker certificateChecker) { public String getDisplayMessage(CertificateChecker certificateChecker) {
return certificateChecker.getViolationDisplayMessage(this); return certificateChecker.getViolationDisplayMessage(this);

View file

@ -127,7 +127,7 @@ public final class TmchCertificateAuthority {
*/ */
public void verify(X509Certificate cert) throws GeneralSecurityException { public void verify(X509Certificate cert) throws GeneralSecurityException {
synchronized (TmchCertificateAuthority.class) { synchronized (TmchCertificateAuthority.class) {
X509Utils.verifyCertificate(getAndValidateRoot(), getCrl(), cert, clock.nowUtc().toDate()); X509Utils.verifyCertificate(getAndValidateRoot(), getCrl(), cert, clock.nowUtc());
} }
} }
@ -151,7 +151,7 @@ public final class TmchCertificateAuthority {
} catch (Exception e) { } catch (Exception e) {
logger.atWarning().withCause(e).log("Old CRL is invalid, ignored during CRL update."); logger.atWarning().withCause(e).log("Old CRL is invalid, ignored during CRL update.");
} }
X509Utils.verifyCrl(getAndValidateRoot(), oldCrl, newCrl, clock.nowUtc().toDate()); X509Utils.verifyCrl(getAndValidateRoot(), oldCrl, newCrl, clock.nowUtc());
TmchCrl.set(asciiCrl, url); TmchCrl.set(asciiCrl, url);
} }

View file

@ -22,7 +22,7 @@ import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.TokenType; import google.registry.model.domain.token.AllocationToken.TokenType;
import google.registry.model.domain.token.BulkPricingPackage; import google.registry.model.domain.token.BulkPricingPackage;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import java.util.Date; import google.registry.tools.params.DateTimeParameter;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -56,9 +56,11 @@ abstract class CreateOrUpdateBulkPricingPackageCommand extends MutatingCommand {
@Nullable @Nullable
@Parameter( @Parameter(
names = "--next_billing_date", names = "--next_billing_date",
converter = DateTimeParameter.class,
validateWith = DateTimeParameter.class,
description = description =
"The next date that the bulk pricing package should be billed for its annual fee") "The next date that the bulk pricing package should be billed for its annual fee")
Date nextBillingDate; DateTime nextBillingDate;
/** Returns the existing BulkPricingPackage or null if it does not exist. */ /** Returns the existing BulkPricingPackage or null if it does not exist. */
@Nullable @Nullable
@ -105,9 +107,7 @@ abstract class CreateOrUpdateBulkPricingPackageCommand extends MutatingCommand {
Optional.ofNullable(maxCreates).ifPresent(builder::setMaxCreates); Optional.ofNullable(maxCreates).ifPresent(builder::setMaxCreates);
Optional.ofNullable(price).ifPresent(builder::setBulkPrice); Optional.ofNullable(price).ifPresent(builder::setBulkPrice);
Optional.ofNullable(nextBillingDate) Optional.ofNullable(nextBillingDate)
.ifPresent( .ifPresent(nextBillingDate -> builder.setNextBillingDate(nextBillingDate));
nextBillingDate ->
builder.setNextBillingDate(new DateTime(nextBillingDate)));
if (clearLastNotificationSent()) { if (clearLastNotificationSent()) {
builder.setLastNotificationSent(null); builder.setLastNotificationSent(null);
} }

View file

@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import google.registry.module.backend.BackendRequestComponent; import google.registry.module.backend.BackendRequestComponent;
import google.registry.module.bsa.BsaRequestComponent; import google.registry.module.bsa.BsaRequestComponent;
import google.registry.module.frontend.FrontendRequestComponent; import google.registry.module.frontend.FrontendRequestComponent;
@ -28,7 +29,6 @@ import google.registry.testing.TestDataHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.testcontainers.shaded.com.google.common.collect.ImmutableMap;
/** Unit tests for {@link RequestComponent}. */ /** Unit tests for {@link RequestComponent}. */
public class RequestComponentTest { public class RequestComponentTest {

View file

@ -40,7 +40,6 @@ import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
import com.google.common.net.HttpHeaders; import com.google.common.net.HttpHeaders;
import com.google.common.net.MediaType; import com.google.common.net.MediaType;
import com.google.common.truth.Truth8;
import com.google.protobuf.Timestamp; import com.google.protobuf.Timestamp;
import com.google.protobuf.util.Timestamps; import com.google.protobuf.util.Timestamps;
import dagger.Module; import dagger.Module;
@ -133,7 +132,7 @@ public class CloudTasksHelper implements Serializable {
public void assertTasksEnqueuedWithProperty( public void assertTasksEnqueuedWithProperty(
String queueName, Function<Task, String> propertyGetter, String... expectedTaskProperties) { String queueName, Function<Task, String> propertyGetter, String... expectedTaskProperties) {
// Ordering is irrelevant but duplicates should be considered independently. // Ordering is irrelevant but duplicates should be considered independently.
Truth8.assertThat(getTestTasksFor(queueName).stream().map(propertyGetter)) assertThat(getTestTasksFor(queueName).stream().map(propertyGetter))
.containsExactly((Object[]) expectedTaskProperties); .containsExactly((Object[]) expectedTaskProperties);
} }

View file

@ -53,7 +53,7 @@ public class CreateBulkPricingPackageCommandTest
"--max_domains=100", "--max_domains=100",
"--max_creates=500", "--max_creates=500",
"--price=USD 1000.00", "--price=USD 1000.00",
"--next_billing_date=2012-03-17", "--next_billing_date=2012-03-17T00:00:00Z",
"abc123"); "abc123");
Optional<BulkPricingPackage> bulkPricingPackageOptional = Optional<BulkPricingPackage> bulkPricingPackageOptional =
@ -161,7 +161,7 @@ public class CreateBulkPricingPackageCommandTest
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE)) .setAllowedEppActions(ImmutableSet.of(CommandName.CREATE))
.setDiscountFraction(1) .setDiscountFraction(1)
.build()); .build());
runCommandForced("--price=USD 1000.00", "--next_billing_date=2012-03-17", "abc123"); runCommandForced("--price=USD 1000.00", "--next_billing_date=2012-03-17T00:00:00Z", "abc123");
Optional<BulkPricingPackage> bulkPricingPackageOptional = Optional<BulkPricingPackage> bulkPricingPackageOptional =
tm().transact(() -> BulkPricingPackage.loadByTokenString("abc123")); tm().transact(() -> BulkPricingPackage.loadByTokenString("abc123"));
assertThat(bulkPricingPackageOptional).isPresent(); assertThat(bulkPricingPackageOptional).isPresent();

View file

@ -69,7 +69,7 @@ public class UpdateBulkPricingPackageCommandTest
"--max_domains=200", "--max_domains=200",
"--max_creates=1000", "--max_creates=1000",
"--price=USD 2000.00", "--price=USD 2000.00",
"--next_billing_date=2013-03-17", "--next_billing_date=2013-03-17T00:00:00Z",
"--clear_last_notification_sent", "--clear_last_notification_sent",
"abc123"); "abc123");
@ -106,7 +106,7 @@ public class UpdateBulkPricingPackageCommandTest
"--max_domains=100", "--max_domains=100",
"--max_creates=500", "--max_creates=500",
"--price=USD 1000.00", "--price=USD 1000.00",
"--next_billing_date=2012-03-17", "--next_billing_date=2012-03-17T00:00:00Z",
"nullPackage")); "nullPackage"));
Truth.assertThat(thrown.getMessage()) Truth.assertThat(thrown.getMessage())
.isEqualTo("BulkPricingPackage with token nullPackage does not exist"); .isEqualTo("BulkPricingPackage with token nullPackage does not exist");
@ -117,7 +117,7 @@ public class UpdateBulkPricingPackageCommandTest
runCommandForced( runCommandForced(
"--max_creates=1000", "--max_creates=1000",
"--price=USD 2000.00", "--price=USD 2000.00",
"--next_billing_date=2013-03-17", "--next_billing_date=2013-03-17T00:00:00Z",
"--clear_last_notification_sent", "--clear_last_notification_sent",
"abc123"); "abc123");
@ -159,7 +159,7 @@ public class UpdateBulkPricingPackageCommandTest
runCommandForced( runCommandForced(
"--max_domains=200", "--max_domains=200",
"--max_creates=1000", "--max_creates=1000",
"--next_billing_date=2013-03-17", "--next_billing_date=2013-03-17T00:00:00Z",
"--clear_last_notification_sent", "--clear_last_notification_sent",
"abc123"); "abc123");

View file

@ -19,6 +19,7 @@ import static google.registry.networking.handler.SslInitializerTestUtils.getKeyP
import static google.registry.networking.handler.SslInitializerTestUtils.setUpSslChannel; import static google.registry.networking.handler.SslInitializerTestUtils.setUpSslChannel;
import static google.registry.networking.handler.SslInitializerTestUtils.signKeyPair; import static google.registry.networking.handler.SslInitializerTestUtils.signKeyPair;
import static google.registry.networking.handler.SslInitializerTestUtils.verifySslException; import static google.registry.networking.handler.SslInitializerTestUtils.verifySslException;
import static org.joda.time.DateTimeZone.UTC;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import google.registry.util.SelfSignedCaCertificate; import google.registry.util.SelfSignedCaCertificate;
@ -43,12 +44,10 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.net.ssl.SSLException; import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
import org.joda.time.DateTime;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
@ -62,7 +61,7 @@ import org.junit.jupiter.params.provider.MethodSource;
* the overhead of routing traffic through the network layer, even if it were to go through * the overhead of routing traffic through the network layer, even if it were to go through
* loopback. It also alleviates the need to pick a free port to use. * loopback. It also alleviates the need to pick a free port to use.
* *
* <p>The local addresses used in each test method must to be different, otherwise tests run in * <p>The local addresses used in each test method must be different, otherwise tests run in
* parallel may interfere with each other. * parallel may interfere with each other.
*/ */
class SslClientInitializerTest { class SslClientInitializerTest {
@ -204,7 +203,7 @@ class SslClientInitializerTest {
// Generate a new key pair. // Generate a new key pair.
KeyPair keyPair = getKeyPair(); KeyPair keyPair = getKeyPair();
// Generate a self signed certificate, and use it to sign the key pair. // Generate a self-signed certificate, and use it to sign the key pair.
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create(); SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create();
X509Certificate cert = signKeyPair(ssc, keyPair, SSL_HOST); X509Certificate cert = signKeyPair(ssc, keyPair, SSL_HOST);
@ -212,7 +211,7 @@ class SslClientInitializerTest {
PrivateKey privateKey = keyPair.getPrivate(); PrivateKey privateKey = keyPair.getPrivate();
nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert)); nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
// Set up the client to trust the self signed cert used to sign the cert that server provides. // Set up the client to trust the self-signed cert used to sign the cert that server provides.
SslClientInitializer<LocalChannel> sslClientInitializer = SslClientInitializer<LocalChannel> sslClientInitializer =
new SslClientInitializer<>( new SslClientInitializer<>(
sslProvider, sslProvider,
@ -239,21 +238,17 @@ class SslClientInitializerTest {
// Generate a new key pair. // Generate a new key pair.
KeyPair keyPair = getKeyPair(); KeyPair keyPair = getKeyPair();
// Generate a self signed certificate, and use it to sign the key pair. // Generate a self-signed certificate, and use it to sign the key pair.
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create(); SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create();
X509Certificate cert = X509Certificate cert =
signKeyPair( signKeyPair(
ssc, ssc, keyPair, SSL_HOST, DateTime.now(UTC).minusDays(2), DateTime.now(UTC).minusDays(1));
keyPair,
SSL_HOST,
Date.from(Instant.now().minus(Duration.ofDays(2))),
Date.from(Instant.now().minus(Duration.ofDays(1))));
// Set up the server to use the signed cert and private key to perform handshake; // Set up the server to use the signed cert and private key to perform handshake;
PrivateKey privateKey = keyPair.getPrivate(); PrivateKey privateKey = keyPair.getPrivate();
nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert)); nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
// Set up the client to trust the self signed cert used to sign the cert that server provides. // Set up the client to trust the self-signed cert used to sign the cert that server provides.
SslClientInitializer<LocalChannel> sslClientInitializer = SslClientInitializer<LocalChannel> sslClientInitializer =
new SslClientInitializer<>( new SslClientInitializer<>(
sslProvider, sslProvider,
@ -280,21 +275,17 @@ class SslClientInitializerTest {
// Generate a new key pair. // Generate a new key pair.
KeyPair keyPair = getKeyPair(); KeyPair keyPair = getKeyPair();
// Generate a self signed certificate, and use it to sign the key pair. // Generate a self-signed certificate, and use it to sign the key pair.
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create(); SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create();
X509Certificate cert = X509Certificate cert =
signKeyPair( signKeyPair(
ssc, ssc, keyPair, SSL_HOST, DateTime.now(UTC).plusDays(1), DateTime.now(UTC).plusDays(2));
keyPair,
SSL_HOST,
Date.from(Instant.now().plus(Duration.ofDays(1))),
Date.from(Instant.now().plus(Duration.ofDays(2))));
// Set up the server to use the signed cert and private key to perform handshake; // Set up the server to use the signed cert and private key to perform handshake;
PrivateKey privateKey = keyPair.getPrivate(); PrivateKey privateKey = keyPair.getPrivate();
nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert)); nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
// Set up the client to trust the self signed cert used to sign the cert that server provides. // Set up the client to trust the self-signed cert used to sign the cert that server provides.
SslClientInitializer<LocalChannel> sslClientInitializer = SslClientInitializer<LocalChannel> sslClientInitializer =
new SslClientInitializer<>( new SslClientInitializer<>(
sslProvider, sslProvider,
@ -333,7 +324,7 @@ class SslClientInitializerTest {
SslClientInitializerTest::hostProvider, SslClientInitializerTest::hostProvider,
SslClientInitializerTest::portProvider, SslClientInitializerTest::portProvider,
ImmutableList.of(serverSsc.cert()), ImmutableList.of(serverSsc.cert()),
() -> clientSsc.key(), clientSsc::key,
() -> ImmutableList.of(clientSsc.cert())); () -> ImmutableList.of(clientSsc.cert()));
nettyExtension.setUpClient(localAddress, sslClientInitializer); nettyExtension.setUpClient(localAddress, sslClientInitializer);
@ -360,7 +351,7 @@ class SslClientInitializerTest {
// Generate a new key pair. // Generate a new key pair.
KeyPair keyPair = getKeyPair(); KeyPair keyPair = getKeyPair();
// Generate a self signed certificate, and use it to sign the key pair. // Generate a self-signed certificate, and use it to sign the key pair.
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create(); SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create();
X509Certificate cert = signKeyPair(ssc, keyPair, "wrong.com"); X509Certificate cert = signKeyPair(ssc, keyPair, "wrong.com");
@ -368,7 +359,7 @@ class SslClientInitializerTest {
PrivateKey privateKey = keyPair.getPrivate(); PrivateKey privateKey = keyPair.getPrivate();
nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert)); nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
// Set up the client to trust the self signed cert used to sign the cert that server provides. // Set up the client to trust the self-signed cert used to sign the cert that server provides.
SslClientInitializer<LocalChannel> sslClientInitializer = SslClientInitializer<LocalChannel> sslClientInitializer =
new SslClientInitializer<>( new SslClientInitializer<>(
sslProvider, sslProvider,
@ -379,7 +370,7 @@ class SslClientInitializerTest {
null); null);
nettyExtension.setUpClient(localAddress, sslClientInitializer); nettyExtension.setUpClient(localAddress, sslClientInitializer);
// When the client rejects the server cert due to wrong hostname, both the client and server // When the client rejects the server cert due to the wrong hostname, both the client and server
// should throw exceptions. // should throw exceptions.
nettyExtension.assertThatClientRootCause().isInstanceOf(CertificateException.class); nettyExtension.assertThatClientRootCause().isInstanceOf(CertificateException.class);
nettyExtension.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST); nettyExtension.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST);

View file

@ -15,6 +15,7 @@
package google.registry.networking.handler; package google.registry.networking.handler;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.joda.time.DateTimeZone.UTC;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
@ -27,9 +28,6 @@ import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500Name;
@ -40,6 +38,7 @@ import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.joda.time.DateTime;
/** /**
* Utility class that provides methods used by {@link SslClientInitializerTest} and {@link * Utility class that provides methods used by {@link SslClientInitializerTest} and {@link
@ -67,13 +66,13 @@ public final class SslInitializerTestUtils {
} }
/** /**
* Signs the given key pair with the given self signed certificate to generate a certificate with * Signs the given key pair with the given self-signed certificate to generate a certificate with
* the given validity range. * the given validity range.
* *
* @return signed public key (of the key pair) certificate * @return signed public key (of the key pair) certificate
*/ */
public static X509Certificate signKeyPair( public static X509Certificate signKeyPair(
SelfSignedCaCertificate ssc, KeyPair keyPair, String hostname, Date from, Date to) SelfSignedCaCertificate ssc, KeyPair keyPair, String hostname, DateTime from, DateTime to)
throws Exception { throws Exception {
X500Name subjectDnName = new X500Name("CN=" + hostname); X500Name subjectDnName = new X500Name("CN=" + hostname);
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis()); BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
@ -81,7 +80,12 @@ public final class SslInitializerTestUtils {
ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(ssc.key()); ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(ssc.key());
X509v3CertificateBuilder v3CertGen = X509v3CertificateBuilder v3CertGen =
new JcaX509v3CertificateBuilder( new JcaX509v3CertificateBuilder(
issuerDnName, serialNumber, from, to, subjectDnName, keyPair.getPublic()); issuerDnName,
serialNumber,
from.toDate(),
to.toDate(),
subjectDnName,
keyPair.getPublic());
X509CertificateHolder certificateHolder = v3CertGen.build(sigGen); X509CertificateHolder certificateHolder = v3CertGen.build(sigGen);
return new JcaX509CertificateConverter() return new JcaX509CertificateConverter()
@ -90,7 +94,7 @@ public final class SslInitializerTestUtils {
} }
/** /**
* Signs the given key pair with the given self signed certificate to generate a certificate that * Signs the given key pair with the given self-signed certificate to generate a certificate that
* is valid from yesterday to tomorrow. * is valid from yesterday to tomorrow.
* *
* @return signed public key (of the key pair) certificate * @return signed public key (of the key pair) certificate
@ -98,11 +102,7 @@ public final class SslInitializerTestUtils {
public static X509Certificate signKeyPair( public static X509Certificate signKeyPair(
SelfSignedCaCertificate ssc, KeyPair keyPair, String hostname) throws Exception { SelfSignedCaCertificate ssc, KeyPair keyPair, String hostname) throws Exception {
return signKeyPair( return signKeyPair(
ssc, ssc, keyPair, hostname, DateTime.now(UTC).minusDays(1), DateTime.now(UTC).plusDays(1));
keyPair,
hostname,
Date.from(Instant.now().minus(Duration.ofDays(1))),
Date.from(Instant.now().plus(Duration.ofDays(1))));
} }
/** /**
@ -110,7 +110,7 @@ public final class SslInitializerTestUtils {
* and verifies if it is echoed back correctly. * and verifies if it is echoed back correctly.
* *
* @param certs The certificate that the server should provide. * @param certs The certificate that the server should provide.
* @return The SSL session in current channel, can be used for further validation. * @return The SSL session in the current channel, can be used for further validation.
*/ */
static SSLSession setUpSslChannel(Channel channel, X509Certificate... certs) throws Exception { static SSLSession setUpSslChannel(Channel channel, X509Certificate... certs) throws Exception {
SslHandler sslHandler = channel.pipeline().get(SslHandler.class); SslHandler sslHandler = channel.pipeline().get(SslHandler.class);

View file

@ -20,6 +20,7 @@ import static google.registry.networking.handler.SslInitializerTestUtils.setUpSs
import static google.registry.networking.handler.SslInitializerTestUtils.signKeyPair; import static google.registry.networking.handler.SslInitializerTestUtils.signKeyPair;
import static google.registry.networking.handler.SslInitializerTestUtils.verifySslException; import static google.registry.networking.handler.SslInitializerTestUtils.verifySslException;
import static google.registry.networking.handler.SslServerInitializer.CLIENT_CERTIFICATE_PROMISE_KEY; import static google.registry.networking.handler.SslServerInitializer.CLIENT_CERTIFICATE_PROMISE_KEY;
import static org.joda.time.DateTimeZone.UTC;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -41,11 +42,8 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngine;
@ -53,6 +51,7 @@ import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
import org.joda.time.DateTime;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
@ -66,7 +65,7 @@ import org.junit.jupiter.params.provider.MethodSource;
* the overhead of routing traffic through the network layer, even if it were to go through * the overhead of routing traffic through the network layer, even if it were to go through
* loopback. It also alleviates the need to pick a free port to use. * loopback. It also alleviates the need to pick a free port to use.
* *
* <p>The local addresses used in each test method must to be different, otherwise tests run in * <p>The local addresses used in each test method must be different, otherwise tests run in
* parallel may interfere with each other. * parallel may interfere with each other.
*/ */
class SslServerInitializerTest { class SslServerInitializerTest {
@ -202,9 +201,7 @@ class SslServerInitializerTest {
localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert())); localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert()));
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate clientSsc =
SelfSignedCaCertificate.create( SelfSignedCaCertificate.create(
"CLIENT", "CLIENT", DateTime.now(UTC).minusDays(2), DateTime.now(UTC).plusDays(1));
Date.from(Instant.now().minus(Duration.ofDays(2))),
Date.from(Instant.now().plus(Duration.ofDays(1))));
nettyExtension.setUpClient( nettyExtension.setUpClient(
localAddress, localAddress,
getClientHandler( getClientHandler(
@ -237,9 +234,7 @@ class SslServerInitializerTest {
Suppliers.ofInstance(ImmutableList.of(serverSsc.cert())))); Suppliers.ofInstance(ImmutableList.of(serverSsc.cert()))));
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate clientSsc =
SelfSignedCaCertificate.create( SelfSignedCaCertificate.create(
"CLIENT", "CLIENT", DateTime.now(UTC).minusDays(2), DateTime.now(UTC).plusDays(1));
Date.from(Instant.now().minus(Duration.ofDays(2))),
Date.from(Instant.now().plus(Duration.ofDays(1))));
nettyExtension.setUpClient( nettyExtension.setUpClient(
localAddress, localAddress,
getClientHandler( getClientHandler(
@ -271,20 +266,18 @@ class SslServerInitializerTest {
localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert())); localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert()));
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate clientSsc =
SelfSignedCaCertificate.create( SelfSignedCaCertificate.create(
"CLIENT", "CLIENT", DateTime.now(UTC).minusDays(2), DateTime.now(UTC).plusDays(1));
Date.from(Instant.now().minus(Duration.ofDays(2))),
Date.from(Instant.now().plus(Duration.ofDays(1))));
nettyExtension.setUpClient( nettyExtension.setUpClient(
localAddress, localAddress,
getClientHandler( getClientHandler(
sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert(), "TLSv1.1", null)); sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert(), "TLSv1.1", null));
ImmutableList<Integer> jdkVersion = ImmutableList<Integer> jdkVersion =
Arrays.asList(System.getProperty("java.version").split("\\.")).stream() Arrays.stream(System.getProperty("java.version").split("\\."))
.map(Integer::parseInt) .map(Integer::parseInt)
.collect(ImmutableList.toImmutableList()); .collect(ImmutableList.toImmutableList());
// In JDK v11.0.11 and above TLS 1.1 is not supported any more, in which case attempting to // In JDK v11.0.11 and above, TLS 1.1 is not supported anymore, in which case attempting to
// connect with TLS 1.1 results in a ClosedChannelException instead of a SSLHandShakeException. // connect with TLS 1.1 results in a ClosedChannelException instead of a SSLHandShakeException.
// See https://www.oracle.com/java/technologies/javase/11-0-11-relnotes.html#JDK-8202343 // See https://www.oracle.com/java/technologies/javase/11-0-11-relnotes.html#JDK-8202343
Class<? extends Exception> rootCause = Class<? extends Exception> rootCause =
@ -309,9 +302,7 @@ class SslServerInitializerTest {
localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert())); localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert()));
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate clientSsc =
SelfSignedCaCertificate.create( SelfSignedCaCertificate.create(
"CLIENT", "CLIENT", DateTime.now(UTC).minusDays(2), DateTime.now(UTC).minusDays(1));
Date.from(Instant.now().minus(Duration.ofDays(2))),
Date.from(Instant.now().minus(Duration.ofDays(1))));
nettyExtension.setUpClient( nettyExtension.setUpClient(
localAddress, localAddress,
getClientHandler(sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert())); getClientHandler(sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
@ -332,9 +323,7 @@ class SslServerInitializerTest {
localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert())); localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert()));
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate clientSsc =
SelfSignedCaCertificate.create( SelfSignedCaCertificate.create(
"CLIENT", "CLIENT", DateTime.now(UTC).plusDays(1), DateTime.now(UTC).plusDays(2));
Date.from(Instant.now().plus(Duration.ofDays(1))),
Date.from(Instant.now().plus(Duration.ofDays(2))));
nettyExtension.setUpClient( nettyExtension.setUpClient(
localAddress, localAddress,
getClientHandler(sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert())); getClientHandler(sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
@ -446,8 +435,8 @@ class SslServerInitializerTest {
localAddress, localAddress,
getClientHandler(sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert())); getClientHandler(sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
// When the client rejects the server cert due to wrong hostname, both the server and the client // When the client rejects the server cert due to the wrong hostname, both the server and the
// throw exceptions. // client throw exceptions.
nettyExtension.assertThatClientRootCause().isInstanceOf(CertificateException.class); nettyExtension.assertThatClientRootCause().isInstanceOf(CertificateException.class);
nettyExtension.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST); nettyExtension.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST);
nettyExtension.assertThatServerRootCause().isInstanceOf(SSLException.class); nettyExtension.assertThatServerRootCause().isInstanceOf(SSLException.class);

View file

@ -15,6 +15,7 @@
package google.registry.util; package google.registry.util;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static org.joda.time.DateTimeZone.UTC;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import java.math.BigInteger; import java.math.BigInteger;
@ -23,9 +24,6 @@ import java.security.KeyPairGenerator;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.Random; import java.util.Random;
import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500Name;
@ -44,9 +42,8 @@ import org.joda.time.DateTime;
public class SelfSignedCaCertificate { public class SelfSignedCaCertificate {
private static final String DEFAULT_ISSUER_FQDN = "registry-test"; private static final String DEFAULT_ISSUER_FQDN = "registry-test";
private static final Date DEFAULT_NOT_BEFORE = private static final DateTime DEFAULT_NOT_BEFORE = DateTime.now(UTC).minusHours(1);
Date.from(Instant.now().minus(Duration.ofHours(1))); private static final DateTime DEFAULT_NOT_AFTER = DateTime.now(UTC).plusDays(1);
private static final Date DEFAULT_NOT_AFTER = Date.from(Instant.now().plus(Duration.ofDays(1)));
private static final Random RANDOM = new Random(); private static final Random RANDOM = new Random();
private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider(); private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider();
@ -80,24 +77,14 @@ public class SelfSignedCaCertificate {
return create(fqdn, DEFAULT_NOT_BEFORE, DEFAULT_NOT_AFTER); return create(fqdn, DEFAULT_NOT_BEFORE, DEFAULT_NOT_AFTER);
} }
public static SelfSignedCaCertificate create(String fqdn, Date from, Date to) throws Exception {
return create(keyGen.generateKeyPair(), fqdn, from, to);
}
public static SelfSignedCaCertificate create(String fqdn, DateTime from, DateTime to) public static SelfSignedCaCertificate create(String fqdn, DateTime from, DateTime to)
throws Exception { throws Exception {
return create(keyGen.generateKeyPair(), fqdn, from.toDate(), to.toDate()); return create(keyGen.generateKeyPair(), fqdn, from, to);
}
public static SelfSignedCaCertificate create(KeyPair keyPair, String fqdn, Date from, Date to)
throws Exception {
return new SelfSignedCaCertificate(keyPair.getPrivate(), createCaCert(keyPair, fqdn, from, to));
} }
public static SelfSignedCaCertificate create( public static SelfSignedCaCertificate create(
KeyPair keyPair, String fqdn, DateTime from, DateTime to) throws Exception { KeyPair keyPair, String fqdn, DateTime from, DateTime to) throws Exception {
return new SelfSignedCaCertificate( return new SelfSignedCaCertificate(keyPair.getPrivate(), createCaCert(keyPair, fqdn, from, to));
keyPair.getPrivate(), createCaCert(keyPair, fqdn, from.toDate(), to.toDate()));
} }
static KeyPairGenerator createKeyPairGenerator() { static KeyPairGenerator createKeyPairGenerator() {
@ -111,7 +98,7 @@ public class SelfSignedCaCertificate {
} }
/** Returns a self-signed Certificate Authority (CA) certificate. */ /** Returns a self-signed Certificate Authority (CA) certificate. */
static X509Certificate createCaCert(KeyPair keyPair, String fqdn, Date from, Date to) static X509Certificate createCaCert(KeyPair keyPair, String fqdn, DateTime from, DateTime to)
throws Exception { throws Exception {
X500Name owner = new X500Name("CN=" + fqdn); X500Name owner = new X500Name("CN=" + fqdn);
String publicKeyAlg = keyPair.getPublic().getAlgorithm(); String publicKeyAlg = keyPair.getPublic().getAlgorithm();
@ -121,7 +108,12 @@ public class SelfSignedCaCertificate {
new JcaContentSignerBuilder(signatureAlgorithm).build(keyPair.getPrivate()); new JcaContentSignerBuilder(signatureAlgorithm).build(keyPair.getPrivate());
X509v3CertificateBuilder builder = X509v3CertificateBuilder builder =
new JcaX509v3CertificateBuilder( new JcaX509v3CertificateBuilder(
owner, new BigInteger(64, RANDOM), from, to, owner, keyPair.getPublic()); owner,
new BigInteger(64, RANDOM),
from.toDate(),
to.toDate(),
owner,
keyPair.getPublic());
// Mark cert as CA by adding basicConstraint with cA=true to the builder // Mark cert as CA by adding basicConstraint with cA=true to the builder
BasicConstraints basicConstraints = new BasicConstraints(true); BasicConstraints basicConstraints = new BasicConstraints(true);

View file

@ -41,11 +41,11 @@ import java.security.cert.X509CRL;
import java.security.cert.X509CRLEntry; import java.security.cert.X509CRLEntry;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.Base64; import java.util.Base64;
import java.util.Date;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.Tainted; import javax.annotation.Tainted;
import org.joda.time.DateTime;
import org.joda.time.DateTimeComparator; import org.joda.time.DateTimeComparator;
/** X.509 Public Key Infrastructure (PKI) helper functions. */ /** X.509 Public Key Infrastructure (PKI) helper functions. */
@ -140,13 +140,13 @@ public final class X509Utils {
* <p>Support for certificate chains has not been implemented. * <p>Support for certificate chains has not been implemented.
* *
* @throws GeneralSecurityException for unsupported protocols, certs not signed by the TMCH, * @throws GeneralSecurityException for unsupported protocols, certs not signed by the TMCH,
* parsing errors, encoding errors, if the CRL is expired, or if the CRL is older than the * parsing errors, encoding errors, if the CRL is expired, or if the CRL is older than the one
* one currently in memory. * currently in memory.
*/ */
public static void verifyCertificate( public static void verifyCertificate(
X509Certificate rootCert, X509CRL crl, @Tainted X509Certificate cert, Date now) X509Certificate rootCert, X509CRL crl, @Tainted X509Certificate cert, DateTime now)
throws GeneralSecurityException { throws GeneralSecurityException {
cert.checkValidity(checkNotNull(now, "now")); cert.checkValidity(checkNotNull(now, "now").toDate());
cert.verify(rootCert.getPublicKey()); cert.verify(rootCert.getPublicKey());
if (crl.isRevoked(cert)) { if (crl.isRevoked(cert)) {
X509CRLEntry entry = crl.getRevokedCertificate(cert); X509CRLEntry entry = crl.getRevokedCertificate(cert);
@ -168,7 +168,7 @@ public final class X509Utils {
* incorrect keys, and for invalid, old, not-yet-valid or revoked certificates. * incorrect keys, and for invalid, old, not-yet-valid or revoked certificates.
*/ */
public static void verifyCrl( public static void verifyCrl(
X509Certificate rootCert, @Nullable X509CRL oldCrl, @Tainted X509CRL newCrl, Date now) X509Certificate rootCert, @Nullable X509CRL oldCrl, @Tainted X509CRL newCrl, DateTime now)
throws GeneralSecurityException { throws GeneralSecurityException {
if (oldCrl != null if (oldCrl != null
&& DateTimeComparator.getInstance().compare(newCrl.getThisUpdate(), oldCrl.getThisUpdate()) && DateTimeComparator.getInstance().compare(newCrl.getThisUpdate(), oldCrl.getThisUpdate())
@ -178,7 +178,7 @@ public final class X509Utils {
"New CRL is more out of date than our current CRL. %s < %s\n%s", "New CRL is more out of date than our current CRL. %s < %s\n%s",
newCrl.getThisUpdate(), oldCrl.getThisUpdate(), newCrl)); newCrl.getThisUpdate(), oldCrl.getThisUpdate(), newCrl));
} }
if (DateTimeComparator.getInstance().compare(newCrl.getNextUpdate(), now) < 0) { if (DateTimeComparator.getInstance().compare(new DateTime(newCrl.getNextUpdate()), now) < 0) {
throw new CRLException("CRL has expired.\n" + newCrl); throw new CRLException("CRL has expired.\n" + newCrl);
} }
newCrl.verify(rootCert.getPublicKey()); newCrl.verify(rootCert.getPublicKey());