mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-10 06:59:05 +00:00
8374808: Add new methods to KeyStore and KeyStoreSpi that return the creation date as an Instant instead of Date
Reviewed-by: weijun
This commit is contained in:
parent
bfb6de5b2b
commit
264fdc5b4e
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2026, 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,8 @@ import java.security.*;
|
||||
import java.security.cert.*;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.spec.*;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
|
||||
import javax.crypto.*;
|
||||
@ -114,7 +116,7 @@ abstract sealed class KeychainStore extends KeyStoreSpi {
|
||||
// SecCertificateRef. When we delete the key we have to delete all of the corresponding
|
||||
// native objects.
|
||||
static class KeyEntry {
|
||||
Date date; // the creation date of this entry
|
||||
Instant date; // the creation instant of this entry
|
||||
byte[] protectedPrivKey;
|
||||
char[] password;
|
||||
long keyRef; // SecKeyRef for this key
|
||||
@ -124,7 +126,7 @@ abstract sealed class KeychainStore extends KeyStoreSpi {
|
||||
|
||||
// Trusted certificates
|
||||
static class TrustedCertEntry {
|
||||
Date date; // the creation date of this entry
|
||||
Instant date; // the creation instant of this entry
|
||||
|
||||
Certificate cert;
|
||||
long certRef; // SecCertificateRef for this key
|
||||
@ -405,13 +407,32 @@ abstract sealed class KeychainStore extends KeyStoreSpi {
|
||||
* not exist
|
||||
*/
|
||||
public Date engineGetCreationDate(String alias) {
|
||||
Object entry = entries.get(alias.toLowerCase(Locale.ROOT));
|
||||
final Instant instant = this.engineGetCreationInstant(alias);
|
||||
if (instant == null) {
|
||||
return null;
|
||||
}
|
||||
return Date.from(instant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the instant that the entry identified by the given alias was
|
||||
* created.
|
||||
*
|
||||
* @param alias the alias name
|
||||
*
|
||||
* @return the instant that the entry identified by the given alias
|
||||
* was created, or {@code null} if the given alias does not exist
|
||||
*
|
||||
* @since 27
|
||||
*/
|
||||
public Instant engineGetCreationInstant(String alias) {
|
||||
final Object entry = entries.get(alias.toLowerCase(Locale.ROOT));
|
||||
|
||||
if (entry != null) {
|
||||
if (entry instanceof TrustedCertEntry) {
|
||||
return new Date(((TrustedCertEntry)entry).date.getTime());
|
||||
if (entry instanceof TrustedCertEntry trustedCertEntry) {
|
||||
return trustedCertEntry.date;
|
||||
} else {
|
||||
return new Date(((KeyEntry)entry).date.getTime());
|
||||
return ((KeyEntry)entry).date;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
@ -447,7 +468,7 @@ abstract sealed class KeychainStore extends KeyStoreSpi {
|
||||
synchronized(entries) {
|
||||
try {
|
||||
KeyEntry entry = new KeyEntry();
|
||||
entry.date = new Date();
|
||||
entry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
if (key instanceof PrivateKey) {
|
||||
if ((key.getFormat().equals("PKCS#8")) ||
|
||||
@ -525,7 +546,7 @@ abstract sealed class KeychainStore extends KeyStoreSpi {
|
||||
+ "EncryptedPrivateKeyInfo");
|
||||
}
|
||||
|
||||
entry.date = new Date();
|
||||
entry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
if ((chain != null) &&
|
||||
(chain.length != 0)) {
|
||||
@ -927,9 +948,9 @@ abstract sealed class KeychainStore extends KeyStoreSpi {
|
||||
|
||||
// Make a creation date.
|
||||
if (creationDate != 0)
|
||||
tce.date = new Date(creationDate);
|
||||
tce.date = Instant.ofEpochMilli(creationDate);
|
||||
else
|
||||
tce.date = new Date();
|
||||
tce.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
entries.put(alias.toLowerCase(Locale.ROOT), tce);
|
||||
} catch (Exception e) {
|
||||
@ -952,9 +973,9 @@ abstract sealed class KeychainStore extends KeyStoreSpi {
|
||||
|
||||
// Make a creation date.
|
||||
if (creationDate != 0)
|
||||
ke.date = new Date(creationDate);
|
||||
ke.date = Instant.ofEpochMilli(creationDate);
|
||||
else
|
||||
ke.date = new Date();
|
||||
ke.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
// Next, create X.509 Certificate objects from the raw data. This is complicated
|
||||
// because a certificate's public key may be too long for Java's default encryption strength.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2026, 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
|
||||
@ -29,6 +29,8 @@ import sun.security.util.Debug;
|
||||
import sun.security.util.IOUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.DigestOutputStream;
|
||||
@ -70,14 +72,14 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
|
||||
// Private key and supporting certificate chain
|
||||
private static final class PrivateKeyEntry {
|
||||
Date date; // the creation date of this entry
|
||||
Instant date; // the creation date of this entry
|
||||
byte[] protectedKey;
|
||||
Certificate[] chain;
|
||||
}
|
||||
|
||||
// Secret key
|
||||
private static final class SecretKeyEntry {
|
||||
Date date; // the creation date of this entry
|
||||
Instant date; // the creation date of this entry
|
||||
SealedObject sealedKey;
|
||||
|
||||
// Maximum possible length of sealedKey. Used to detect malicious
|
||||
@ -89,7 +91,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
|
||||
// Trusted certificate
|
||||
private static final class TrustedCertEntry {
|
||||
Date date; // the creation date of this entry
|
||||
Instant date; // the creation date of this entry
|
||||
Certificate cert;
|
||||
}
|
||||
|
||||
@ -213,23 +215,38 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
* not exist
|
||||
*/
|
||||
public Date engineGetCreationDate(String alias) {
|
||||
Date date = null;
|
||||
final Instant instant = this.engineGetCreationInstant(alias);
|
||||
if (instant == null) {
|
||||
return null;
|
||||
}
|
||||
return Date.from(instant);
|
||||
}
|
||||
|
||||
Object entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
|
||||
/**
|
||||
* Returns the instant that the entry identified by the given alias was
|
||||
* created.
|
||||
*
|
||||
* @param alias the alias name
|
||||
*
|
||||
* @return the instant that the entry identified by the given alias
|
||||
* was created, or {@code null} if the given alias does not exist
|
||||
*
|
||||
* @since 27
|
||||
*/
|
||||
public Instant engineGetCreationInstant(String alias) {
|
||||
final Object entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
|
||||
|
||||
if (entry != null) {
|
||||
// We have to create a new instance of java.util.Date because
|
||||
// dates are not immutable
|
||||
if (entry instanceof TrustedCertEntry) {
|
||||
date = new Date(((TrustedCertEntry)entry).date.getTime());
|
||||
return ((TrustedCertEntry)entry).date;
|
||||
} else if (entry instanceof PrivateKeyEntry) {
|
||||
date = new Date(((PrivateKeyEntry)entry).date.getTime());
|
||||
return ((PrivateKeyEntry)entry).date;
|
||||
} else {
|
||||
date = new Date(((SecretKeyEntry)entry).date.getTime());
|
||||
return ((SecretKeyEntry)entry).date;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -264,7 +281,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
|
||||
if (key instanceof PrivateKey) {
|
||||
PrivateKeyEntry entry = new PrivateKeyEntry();
|
||||
entry.date = new Date();
|
||||
entry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
// protect the private key
|
||||
entry.protectedKey = keyProtector.protect((PrivateKey)key);
|
||||
@ -282,7 +299,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
|
||||
} else {
|
||||
SecretKeyEntry entry = new SecretKeyEntry();
|
||||
entry.date = new Date();
|
||||
entry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
// seal and store the key
|
||||
entry.sealedKey = keyProtector.seal(key);
|
||||
@ -325,7 +342,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
// We assume it's a private key, because there is no standard
|
||||
// (ASN.1) encoding format for wrapped secret keys
|
||||
PrivateKeyEntry entry = new PrivateKeyEntry();
|
||||
entry.date = new Date();
|
||||
entry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
entry.protectedKey = key.clone();
|
||||
if ((chain != null) &&
|
||||
@ -370,7 +387,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
|
||||
TrustedCertEntry trustedCertEntry = new TrustedCertEntry();
|
||||
trustedCertEntry.cert = cert;
|
||||
trustedCertEntry.date = new Date();
|
||||
trustedCertEntry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
entries.put(alias.toLowerCase(Locale.ENGLISH), trustedCertEntry);
|
||||
}
|
||||
}
|
||||
@ -588,7 +605,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
dos.writeUTF(alias);
|
||||
|
||||
// write the (entry creation) date
|
||||
dos.writeLong(pentry.date.getTime());
|
||||
dos.writeLong(pentry.date.toEpochMilli());
|
||||
|
||||
// write the protected private key
|
||||
dos.writeInt(pentry.protectedKey.length);
|
||||
@ -618,7 +635,9 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
dos.writeUTF(alias);
|
||||
|
||||
// write the (entry creation) date
|
||||
dos.writeLong(((TrustedCertEntry)entry).date.getTime());
|
||||
dos.writeLong(
|
||||
((TrustedCertEntry)entry).date.toEpochMilli()
|
||||
);
|
||||
|
||||
// write the trusted certificate
|
||||
encoded = ((TrustedCertEntry)entry).cert.getEncoded();
|
||||
@ -635,7 +654,9 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
dos.writeUTF(alias);
|
||||
|
||||
// write the (entry creation) date
|
||||
dos.writeLong(((SecretKeyEntry)entry).date.getTime());
|
||||
dos.writeLong(
|
||||
((SecretKeyEntry)entry).date.toEpochMilli()
|
||||
);
|
||||
|
||||
// write the sealed key
|
||||
oos = new ObjectOutputStream(dos);
|
||||
@ -753,7 +774,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
alias = dis.readUTF();
|
||||
|
||||
// read the (entry creation) date
|
||||
entry.date = new Date(dis.readLong());
|
||||
entry.date = Instant.ofEpochMilli(dis.readLong());
|
||||
|
||||
// read the private key
|
||||
entry.protectedKey = IOUtils.readExactlyNBytes(dis, dis.readInt());
|
||||
@ -798,7 +819,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
alias = dis.readUTF();
|
||||
|
||||
// read the (entry creation) date
|
||||
entry.date = new Date(dis.readLong());
|
||||
entry.date = Instant.ofEpochMilli(dis.readLong());
|
||||
|
||||
// read the trusted certificate
|
||||
if (xVersion == 2) {
|
||||
@ -832,7 +853,7 @@ public final class JceKeyStore extends KeyStoreSpi {
|
||||
alias = dis.readUTF();
|
||||
|
||||
// read the (entry creation) date
|
||||
entry.date = new Date(dis.readLong());
|
||||
entry.date = Instant.ofEpochMilli(dis.readLong());
|
||||
|
||||
// read the sealed key
|
||||
try {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
@ -1182,6 +1183,9 @@ public class KeyStore {
|
||||
|
||||
/**
|
||||
* Returns the creation date of the entry identified by the given alias.
|
||||
* <p>
|
||||
* It is recommended to use the {@link #getCreationInstant(String)}
|
||||
* method instead.
|
||||
*
|
||||
* @param alias the alias name
|
||||
*
|
||||
@ -1200,6 +1204,32 @@ public class KeyStore {
|
||||
return keyStoreSpi.engineGetCreationDate(alias);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the instant that the entry identified by the given alias was
|
||||
* created.
|
||||
*
|
||||
* @param alias the alias name
|
||||
*
|
||||
* @return the instant that the entry identified by the given alias
|
||||
* was created, or {@code null} if the given alias does not exist
|
||||
*
|
||||
* @throws KeyStoreException if the keystore has not been initialized
|
||||
* (loaded)
|
||||
*
|
||||
* @since 27
|
||||
*/
|
||||
public final Instant getCreationInstant(String alias)
|
||||
throws KeyStoreException
|
||||
{
|
||||
if (!initialized) {
|
||||
throw new KeyStoreException("Uninitialized keystore");
|
||||
}
|
||||
return keyStoreSpi.engineGetCreationInstant(alias);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assigns the given key to the given alias, protecting it with the given
|
||||
* password.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2026, 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,6 +26,7 @@
|
||||
package java.security;
|
||||
|
||||
import java.io.*;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
|
||||
import java.security.KeyStore.*;
|
||||
@ -127,6 +128,29 @@ public abstract class KeyStoreSpi {
|
||||
*/
|
||||
public abstract Date engineGetCreationDate(String alias);
|
||||
|
||||
/**
|
||||
* Returns the instant that the entry identified by the given alias was
|
||||
* created.
|
||||
*
|
||||
* @apiNote Subclasses should override this method to directly return an
|
||||
* instant.
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation calls {@code engineGetCreationDate(alias)}
|
||||
* and returns the output as an {@code Instant} value.
|
||||
*
|
||||
* @param alias the alias name
|
||||
*
|
||||
* @return the instant that the entry identified by the given alias
|
||||
* was created, or {@code null} if the given alias does not exist
|
||||
*
|
||||
* @since 27
|
||||
*/
|
||||
public Instant engineGetCreationInstant(String alias) {
|
||||
final Date date = engineGetCreationDate(alias);
|
||||
return date == null ? null : date.toInstant();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the given key to the given alias, protecting it with the given
|
||||
* password.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2026, 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
|
||||
@ -35,6 +35,8 @@ import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.InvalidParameterSpecException;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
@ -179,7 +181,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
|
||||
// A keystore entry and associated attributes
|
||||
private static class Entry {
|
||||
Date date; // the creation date of this entry
|
||||
Instant date; // the creation date of this entry
|
||||
String alias;
|
||||
byte[] keyId;
|
||||
Set<KeyStore.Entry.Attribute> attributes;
|
||||
@ -212,7 +214,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
CertEntry(X509Certificate cert, byte[] keyId, String alias,
|
||||
ObjectIdentifier[] trustedKeyUsage,
|
||||
Set<? extends KeyStore.Entry.Attribute> attributes) {
|
||||
this.date = new Date();
|
||||
this.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
this.cert = cert;
|
||||
this.keyId = keyId;
|
||||
this.alias = alias;
|
||||
@ -541,9 +543,28 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
* not exist
|
||||
*/
|
||||
public Date engineGetCreationDate(String alias) {
|
||||
Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
|
||||
final Instant instant = this.engineGetCreationInstant(alias);
|
||||
if (instant == null) {
|
||||
return null;
|
||||
}
|
||||
return Date.from(instant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the instant that the entry identified by the given alias was
|
||||
* created.
|
||||
*
|
||||
* @param alias the alias name
|
||||
*
|
||||
* @return the instant that the entry identified by the given alias
|
||||
* was created, or {@code null} if the given alias does not exist
|
||||
*
|
||||
* @since 27
|
||||
*/
|
||||
public Instant engineGetCreationInstant(String alias) {
|
||||
final Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
|
||||
if (entry != null) {
|
||||
return new Date(entry.date.getTime());
|
||||
return entry.date;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -606,7 +627,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
checkX509Certs(chain);
|
||||
|
||||
PrivateKeyEntry keyEntry = new PrivateKeyEntry();
|
||||
keyEntry.date = new Date();
|
||||
keyEntry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
if ((key.getFormat().equals("PKCS#8")) ||
|
||||
(key.getFormat().equals("PKCS8"))) {
|
||||
@ -651,7 +672,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
|
||||
} else if (key instanceof SecretKey) {
|
||||
SecretKeyEntry keyEntry = new SecretKeyEntry();
|
||||
keyEntry.date = new Date();
|
||||
keyEntry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
// Encode secret key in a PKCS#8
|
||||
DerOutputStream secretKeyInfo = new DerOutputStream();
|
||||
@ -690,7 +711,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
entry.attributes.addAll(attributes);
|
||||
}
|
||||
// set the keyId to current date
|
||||
entry.keyId = ("Time " + (entry.date).getTime()).getBytes(UTF_8);
|
||||
entry.keyId = ("Time " + entry.date.toEpochMilli()).getBytes(UTF_8);
|
||||
// set the alias
|
||||
entry.alias = alias.toLowerCase(Locale.ENGLISH);
|
||||
// add the entry
|
||||
@ -745,7 +766,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
}
|
||||
|
||||
PrivateKeyEntry entry = new PrivateKeyEntry();
|
||||
entry.date = new Date();
|
||||
entry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
if (debug != null) {
|
||||
debug.println("Setting a protected private key at alias '" +
|
||||
@ -753,7 +774,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
}
|
||||
|
||||
// set the keyId to current date
|
||||
entry.keyId = ("Time " + (entry.date).getTime()).getBytes(UTF_8);
|
||||
entry.keyId = ("Time " + entry.date.toEpochMilli()).getBytes(UTF_8);
|
||||
// set the alias
|
||||
entry.alias = alias.toLowerCase(Locale.ENGLISH);
|
||||
|
||||
@ -2411,21 +2432,22 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
|
||||
}
|
||||
}
|
||||
entry.keyId = keyId;
|
||||
// restore date if it exists
|
||||
// restore instant if it exists
|
||||
String keyIdStr = new String(keyId, UTF_8);
|
||||
Date date = null;
|
||||
Instant instant = null;
|
||||
if (keyIdStr.startsWith("Time ")) {
|
||||
try {
|
||||
date = new Date(
|
||||
Long.parseLong(keyIdStr.substring(5)));
|
||||
instant = Instant.ofEpochMilli(
|
||||
Long.parseLong(keyIdStr.substring(5))
|
||||
);
|
||||
} catch (Exception e) {
|
||||
// date has been initialized to null
|
||||
// instant has been initialized to null
|
||||
}
|
||||
}
|
||||
if (date == null) {
|
||||
date = new Date();
|
||||
if (instant == null) {
|
||||
instant = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
}
|
||||
entry.date = date;
|
||||
entry.date = instant;
|
||||
|
||||
if (bagItem instanceof PrivateKeyEntry) {
|
||||
keyList.add(entry);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2026, 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.net.*;
|
||||
import java.security.*;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@ -214,16 +215,32 @@ abstract class DomainKeyStore extends KeyStoreSpi {
|
||||
* not exist
|
||||
*/
|
||||
public Date engineGetCreationDate(String alias) {
|
||||
final Instant instant = this.engineGetCreationInstant(alias);
|
||||
return (instant == null) ? null : Date.from(instant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the instant that the entry identified by the given alias was
|
||||
* created.
|
||||
*
|
||||
* @param alias the alias name
|
||||
*
|
||||
* @return the instant that the entry identified by the given alias
|
||||
* was created, or {@code null} if the given alias does not exist
|
||||
*
|
||||
* @since 27
|
||||
*/
|
||||
public Instant engineGetCreationInstant(String alias) {
|
||||
|
||||
AbstractMap.SimpleEntry<String, Collection<KeyStore>> pair =
|
||||
getKeystoresForReading(alias);
|
||||
Date date = null;
|
||||
Instant instant = null;
|
||||
|
||||
try {
|
||||
String entryAlias = pair.getKey();
|
||||
for (KeyStore keystore : pair.getValue()) {
|
||||
date = keystore.getCreationDate(entryAlias);
|
||||
if (date != null) {
|
||||
instant = keystore.getCreationInstant(entryAlias);
|
||||
if (instant != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -231,7 +248,7 @@ abstract class DomainKeyStore extends KeyStoreSpi {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
return date;
|
||||
return instant;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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,8 @@ import java.security.*;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@ -100,14 +102,14 @@ public abstract sealed class JavaKeyStore extends KeyStoreSpi {
|
||||
|
||||
// Private keys and their supporting certificate chains
|
||||
private static class KeyEntry {
|
||||
Date date; // the creation date of this entry
|
||||
Instant date; // the creation date of this entry
|
||||
byte[] protectedPrivKey;
|
||||
Certificate[] chain;
|
||||
}
|
||||
|
||||
// Trusted certificates
|
||||
private static class TrustedCertEntry {
|
||||
Date date; // the creation date of this entry
|
||||
Instant date; // the creation date of this entry
|
||||
Certificate cert;
|
||||
}
|
||||
|
||||
@ -236,13 +238,31 @@ public abstract sealed class JavaKeyStore extends KeyStoreSpi {
|
||||
* not exist
|
||||
*/
|
||||
public Date engineGetCreationDate(String alias) {
|
||||
Object entry = entries.get(convertAlias(alias));
|
||||
final Instant instant = this.engineGetCreationInstant(alias);
|
||||
return instant == null ? null : Date.from(instant);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the instant that the entry identified by the given alias was
|
||||
* created.
|
||||
*
|
||||
* @param alias the alias name
|
||||
*
|
||||
* @return the instant that the entry identified by the given alias
|
||||
* was created, or {@code null} if the given alias does not exist
|
||||
*
|
||||
* @since 27
|
||||
*/
|
||||
public Instant engineGetCreationInstant(String alias) {
|
||||
final Object entry = entries.get(convertAlias(alias));
|
||||
|
||||
if (entry != null) {
|
||||
if (entry instanceof TrustedCertEntry) {
|
||||
return new Date(((TrustedCertEntry)entry).date.getTime());
|
||||
return ((TrustedCertEntry)entry).date;
|
||||
} else {
|
||||
return new Date(((KeyEntry)entry).date.getTime());
|
||||
return((KeyEntry)entry).date;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
@ -287,7 +307,7 @@ public abstract sealed class JavaKeyStore extends KeyStoreSpi {
|
||||
try {
|
||||
synchronized(entries) {
|
||||
KeyEntry entry = new KeyEntry();
|
||||
entry.date = new Date();
|
||||
entry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
// Protect the encoding of the key
|
||||
passwordBytes = convertToBytes(password);
|
||||
@ -350,7 +370,7 @@ public abstract sealed class JavaKeyStore extends KeyStoreSpi {
|
||||
}
|
||||
|
||||
KeyEntry entry = new KeyEntry();
|
||||
entry.date = new Date();
|
||||
entry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
entry.protectedPrivKey = key.clone();
|
||||
if ((chain != null) &&
|
||||
@ -391,7 +411,7 @@ public abstract sealed class JavaKeyStore extends KeyStoreSpi {
|
||||
|
||||
TrustedCertEntry trustedCertEntry = new TrustedCertEntry();
|
||||
trustedCertEntry.cert = cert;
|
||||
trustedCertEntry.date = new Date();
|
||||
trustedCertEntry.date = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
entries.put(convertAlias(alias), trustedCertEntry);
|
||||
}
|
||||
}
|
||||
@ -579,7 +599,7 @@ public abstract sealed class JavaKeyStore extends KeyStoreSpi {
|
||||
dos.writeUTF(alias);
|
||||
|
||||
// Write the (entry creation) date
|
||||
dos.writeLong(((KeyEntry)entry).date.getTime());
|
||||
dos.writeLong(((KeyEntry)entry).date.toEpochMilli());
|
||||
|
||||
// Write the protected private key
|
||||
dos.writeInt(((KeyEntry)entry).protectedPrivKey.length);
|
||||
@ -608,7 +628,9 @@ public abstract sealed class JavaKeyStore extends KeyStoreSpi {
|
||||
dos.writeUTF(alias);
|
||||
|
||||
// Write the (entry creation) date
|
||||
dos.writeLong(((TrustedCertEntry)entry).date.getTime());
|
||||
dos.writeLong(
|
||||
((TrustedCertEntry)entry).date.toEpochMilli()
|
||||
);
|
||||
|
||||
// Write the trusted certificate
|
||||
encoded = ((TrustedCertEntry)entry).cert.getEncoded();
|
||||
@ -707,7 +729,7 @@ public abstract sealed class JavaKeyStore extends KeyStoreSpi {
|
||||
alias = dis.readUTF();
|
||||
|
||||
// Read the (entry creation) date
|
||||
entry.date = new Date(dis.readLong());
|
||||
entry.date = Instant.ofEpochMilli(dis.readLong());
|
||||
|
||||
// Read the private key
|
||||
entry.protectedPrivKey =
|
||||
@ -756,7 +778,7 @@ public abstract sealed class JavaKeyStore extends KeyStoreSpi {
|
||||
alias = dis.readUTF();
|
||||
|
||||
// Read the (entry creation) date
|
||||
entry.date = new Date(dis.readLong());
|
||||
entry.date = Instant.ofEpochMilli(dis.readLong());
|
||||
|
||||
// Read the trusted certificate
|
||||
if (xVersion == 2) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2026, 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
|
||||
@ -24,13 +24,18 @@
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.*;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.PEMDecoder;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.time.Instant;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8048621 8133090 8167371 8236671
|
||||
* @bug 8048621 8133090 8167371 8236671 8374808
|
||||
* @enablePreview
|
||||
* @summary Test basic operations with keystores (jks, jceks, pkcs12)
|
||||
* @author Yu-Ching Valerie PENG
|
||||
@ -177,6 +182,8 @@ public class TestKeyStoreBasic {
|
||||
|
||||
// compare the creation date of the 2 key stores for all aliases
|
||||
compareCreationDate(ks, ks2, numEntries);
|
||||
compareCreationInstant(ks, ks2, numEntries);
|
||||
|
||||
// remove the last entry from the 2nd key store
|
||||
numEntries--;
|
||||
ks2.deleteEntry(ALIAS_HEAD + numEntries);
|
||||
@ -213,6 +220,7 @@ public class TestKeyStoreBasic {
|
||||
|
||||
// compare the creation date of the 2 key stores for all aliases
|
||||
compareCreationDate(ks, ks2, numEntries);
|
||||
compareCreationInstant(ks, ks2, numEntries);
|
||||
|
||||
// check setEntry/getEntry with a password protection algorithm
|
||||
if ("PKCS12".equalsIgnoreCase(ks.getType())) {
|
||||
@ -284,6 +292,23 @@ public class TestKeyStoreBasic {
|
||||
}
|
||||
}
|
||||
|
||||
// compare the creation instants - true if all the same
|
||||
private void compareCreationInstant(KeyStore o1, KeyStore o2, int range)
|
||||
throws KeyStoreException {
|
||||
String alias;
|
||||
for (int k = 0; k < range; k++) {
|
||||
alias = ALIAS_HEAD + k;
|
||||
final Instant instant1 = o1.getCreationInstant(alias);
|
||||
final Instant instant2 = o2.getCreationInstant(alias);
|
||||
if (!(instant1.equals(instant2))) {
|
||||
throw new RuntimeException("ERROR: entry creation time (" + k
|
||||
+ ") differs Instants {"
|
||||
+ instant1 + " - "
|
||||
+ instant2 + "}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checks if an exception was caused by specified exception class
|
||||
private static boolean causedBy(Exception e, Class klass) {
|
||||
Throwable cause = e;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2026, 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
|
||||
@ -23,19 +23,30 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8007755
|
||||
* @bug 8007755 8374808
|
||||
* @library /test/lib
|
||||
* @summary Support the logical grouping of keystores
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.*;
|
||||
import java.security.DomainLoadStoreParameter;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.*;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.*;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
@ -205,17 +216,26 @@ public class DKSTest {
|
||||
new KeyStore.TrustedCertificateEntry(cert), null);
|
||||
}
|
||||
|
||||
private static void checkEntries(KeyStore keystore, int expected)
|
||||
private static void checkEntries(KeyStore keystore, int expectedCount)
|
||||
throws Exception {
|
||||
int i = 0;
|
||||
int currCount = 0;
|
||||
for (String alias : Collections.list(keystore.aliases())) {
|
||||
System.out.print(".");
|
||||
i++;
|
||||
currCount++;
|
||||
|
||||
// check creation date and instant
|
||||
if(!keystore.getCreationDate(alias).equals(
|
||||
Date.from(keystore.getCreationInstant(alias)))
|
||||
){
|
||||
throw new RuntimeException(
|
||||
"Creation Date is not the same as Instant timestamp");
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
if (expected != i) {
|
||||
// Check if current count is expected
|
||||
if (expectedCount != currCount) {
|
||||
throw new Exception("Error: unexpected entry count in keystore: " +
|
||||
"loaded=" + i + ", expected=" + expected);
|
||||
"loaded=" + currCount + ", expected=" + expectedCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user