Draft API for JEP-166: Overhaul JKS-JCEKS-PKCS12 Keystores
Vincent Ryan
vincent.x.ryan at oracle.com
Mon Jan 14 14:31:57 UTC 2013
Hello all,
I am seeking feedback on a draft of the public APIs that I believe
are needed to address the features described in JEP-166 [1].
JEP-166 is targeted to JDK 8 Milestone 6 so I am keen to get the
bulk of these API changes integrated into the last remaining build
of M6: Build 75. Note that there will be ample time in Milestone 7
to make API modifications and improvements as necessary.
I have divided the API changes into 5 main sections:
1. To support metadata for keystore entries
2. To support stronger entry protection algorithms
3. To support the destruction of sensitive information
associated with cryptographic keys
4. To support the logical grouping of keystores and entries
5. To support the secure storage of passwords
To speed up the process I am providing the javadoc specification
now and will follow-up with a more complete webrev.
Your comments are welcome.
Thanks.
____
[1] http://openjdk.java.net/jeps/166
===========================================
1. To support metadata for keystore entries
===========================================
This involves adding a new nested interface to the
java.security.KeyStore.Entry interface along with a new
getAttributes method. In addition a new constructor that
takes a set of attributes is defined for each of the
concrete classes that implement KeyStore.Entry.
Finally a new PKCS12Attribute if defined to specifically
support attributes in PKCS12 keystores.
-----------------------------------------------------------
New interface in the java.security.KeyStore.Entry interface
-----------------------------------------------------------
/**
* An attribute associated with a keystore entry.
* It comprises a name and one or more values.
*
* @since 1.8
*/
public interface Attribute {
/**
* Returns the attribute's name.
*
* @return the attribute name
*/
public String getName();
/**
* Returns the attribute's value.
* Multi-valued attributes encode their values as a single string.
*
* @return the attribute value
*/
public String getValue();
}
--------------------------------------------------------
New method in the java.security.KeyStore.Entry interface
--------------------------------------------------------
/**
* Retrieves the attributes associated with an entry.
* <p>
* The default implementation returns an empty {@code Set}.
*
* @return an unmodifiable {@code Set} of attributes, possibly empty
*
* @since 1.8
*/
public default Set<Attribute> getAttributes() { ... };
-------------------------------------------------------------------
New constructor for the java.security.KeyStore.SecretKeyEntry class
-------------------------------------------------------------------
/**
* Constructs a {@code SecretKeyEntry} with a {@code SecretKey} and
* associated entry attributes.
*
* <p> The specified {@code attributes} is cloned before it is stored
* in the new {@code SecretKeyEntry} object.
*
* @param secretKey the {@code SecretKey}
* @param attributes the attributes
*
* @exception NullPointerException if {@code secretKey} or
* {@code attributes} is {@code null}
*
* @since 1.8
*/
public SecretKeyEntry(SecretKey secretKey, Set<Attribute> attributes)
{ ... };
--------------------------------------------------------------------
New constructor for the java.security.KeyStore.PrivateKeyEntry class
--------------------------------------------------------------------
/**
* Constructs a {@code PrivateKeyEntry} with a {@code PrivateKey} and
* corresponding certificate chain and associated entry attributes.
*
* <p> The specified {@code chain} and {@code attributes} are cloned
* before they are stored in the new {@code PrivateKeyEntry} object.
*
* @param privateKey the {@code PrivateKey}
* @param chain an array of {@code Certificate}s
* representing the certificate chain.
* The chain must be ordered and contain a
* {@code Certificate} at index 0
* corresponding to the private key.
* @param attributes the attributes
*
* @exception NullPointerException if {@code privateKey}, {@code chain}
* or {@code attributes} is {@code null}
* @exception IllegalArgumentException if the specified chain has a
* length of 0, if the specified chain does not contain
* {@code Certificate}s of the same type,
* or if the {@code PrivateKey} algorithm
* does not match the algorithm of the {@code PublicKey}
* in the end entity {@code Certificate} (at index 0)
*
* @since 1.8
*/
public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain,
Set<Attribute> attributes) { ... };
------------------------------------------------------------------------
New constructor for java.security.KeyStore.TrustedCertificateEntry class
------------------------------------------------------------------------
/**
* Constructs a {@code TrustedCertificateEntry} with a
* trusted {@code Certificate} and associated entry attributes.
*
* <p> The specified {@code attributes} is cloned before it is stored
* in the new {@code TrustedCertificateEntry} object.
*
* @param trustedCert the trusted {@code Certificate}
* @param attributes the attributes
*
* @exception NullPointerException if {@code trustedCert} or
* {@code attributes} is {@code null}
*
* @since 1.8
*/
public TrustedCertificateEntry(Certificate trustedCert,
Set<Attribute> attributes) { ... };
--------------------------------------
New class in the java.security package
--------------------------------------
/**
* An attribute associated with a PKCS12 keystore entry.
* The attribute name is an ASN.1 Object Identifier and the attribute
* value is a set of arbitrary ASN.1 types.
*
* @since 1.8
*/
public final class PKCS12Attribute implements KeyStore.Entry.Attribute {
/**
* Constructs a PKCS12 attribute from its name and value.
* The name is an ASN.1 Object Identifier represented as a list of
* dot-separated integers.
* A string value is represented as the string itself.
* A binary value is represented as a string of colon-separated
* pairs of hexadecimal digits.
* Multi-valued attributes are represented as a comma-separated
* list of values, enclosed in square brackets. See
* {@link Arrays.toString}.
* <p>
* A string value will be DER-encoded as an ASN.1 UTF8String and a
* binary value will be DER-encoded as an ASN.1 Octet String.
*
* @param name the attribute's identifier
* @param value the attribute's value
*
* @exception NullPointerException if {@code name} or {@code value}
* is {@code null}
* @exception IllegalArgumentException if {@code name} or
* {@code value} is incorrectly formatted
*/
public PKCS12Attribute(String name, String value) { ... };
/**
* Constructs a PKCS12 attribute from its ASN.1 DER encoding.
* The DER encoding is specified by the following ASN.1 definition:
* <pre>
*
* Attribute ::= SEQUENCE {
* type AttributeType,
* values SET OF AttributeValue
* }
* AttributeType ::= OBJECT IDENTIFIER
* AttributeValue ::= ANY defined by type
*
* </pre>
*
* @param encoded the attribute's ASN.1 DER encoding. It is cloned
* to prevent subsequent modificaion.
*
* @exception NullPointerException if {@code encoded} is
* {@code null}
* @exception IllegalArgumentException if {@code encoded} is
* incorrectly formatted
*/
public PKCS12Attribute(byte[] encoded) { ... };
/**
* Returns the attribute's ASN.1 Object Identifier represented as a
* list of dot-separated integers.
*
* @return the attribute's identifier
*/
@Override
public String getName() { ... };
/**
* Returns the attribute's ASN.1 DER-encoded value as a string.
* An ASN.1 DER-encoded value is returned in one of the following
* {@code String} formats:
* <ul>
* <li> the DER encoding of a basic ASN.1 type that has a natural
* string representation is returned as the string itself.
* Such types are currently limited to BOOLEAN, INTEGER,
* OBJECT IDENTIFIER, UTCTime, GeneralizedTime and the
* following six ASN.1 string types: UTF8String,
* PrintableString, T61String, IA5String, BMPString and
* GeneralString.
* <li> the DER encoding of any other ASN.1 type is not decoded but
* returned as a binary string of colon-separated pairs of
* hexadecimal digits.
* </ul>
* Multi-valued attributes are represented as a comma-separated
* list of values, enclosed in square brackets. See
* {@link Arrays.toString}.
*
* @return the attribute value's string encoding
*/
@Override
public String getValue() { ... };
/**
* Returns the attribute's ASN.1 DER encoding.
*
* @return a clone of the attribute's DER encoding
*/
public byte[] getEncoded() { ... };
/**
* Compares this {@code PKCS12Attribute} and a specified object for
* equality.
*
* @param obj the comparison object
*
* @return true if {@code obj} is a {@code PKCS12Attribute} and
* their DER encodings are equal.
*/
@Override
public boolean equals(Object obj) { ... };
/**
* Returns the hashcode for this {@code PKCS12Attribute}.
* The hash code is computed from its DER encoding.
*
* @return the hash code
*/
@Override
public int hashCode() { ... };
/**
* Returns a string representation of this {@code PKCS12Attribute}.
*
* @return a name/value pair separated by an 'equals' symbol
*/
@Override
public String toString() { ... };
}
==================================================
2. To support stronger entry protection algorithms
==================================================
This involves enhancing the KeyStore.PasswordProtection class to
enable a password-based encryption algorithm (PBE) to be specified
along with any necessary parameters. The PBE algorithm is used
to encrypt a keystore entry containing a private key or a secret key
when the KeyStore.setEntry or KeyStore.seyKeyEntry methods are used.
------------------------------------------------------------------
New methods in the java.security.KeyStore.PasswordProtection class
------------------------------------------------------------------
/**
* Creates a password parameter and specifies the protection algorithm
* and associated parameters to use when encrypting a keystore entry.
* <p>
* The specified {@code password} is cloned before it is stored in the
* new {@code PasswordProtection} object.
*
* @param password the password, which may be {@code null}
* @param protectionAlgorithm the encryption algorithm name, for
* example, {@code PBEWithHmacSHA256AndAES_256}.
* See the Cipher section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
* Java Cryptography Architecture Standard Algorithm Name
* Documentation</a>
* for information about standard encryption algorithm names.
* @param protectionParameters the encryption algorithm parameter
* specification, which may be {@code null}
* @exception NullPointerException if {@code protectionAlgorithm} is
* {@code null}
*
* @since 1.8
*/
public PasswordProtection(char[] password, String protectionAlgorithm,
AlgorithmParameterSpec protectionParameters);
/**
* Gets the name of the protection algorithm.
* If none was set then the default algorithm name is returned.
* The default algorithm name for a given keystore type is set using the
* {@code 'keystore.<type>.entryProtectionAlgorithm'} Security property.
* For example, the
* {@code keystore.PKCS12.entryProtectionAlgorithm} property stores the
* name of the default entry protection algorithm used for PKCS12
* keystores.
*
* @return the algorithm name
*
* @since 1.8
*/
public String getProtectionAlgorithm();
/**
* Gets the parameters supplied for the protection algorithm.
*
* @return the algorithm parameter specification, or {@code null},
* if none was set
*
* @since 1.8
*/
public AlgorithmParameterSpec getProtectionParameters();
==========================================================
3. To support the destruction of sensitive key information
==========================================================
This involves defining default method implementations for
the destroy and isDestroyed methods of the
javax.security.auth.Destroyable interface. And modifying
the java.security.PrivateKey and javax.crypto.SecretKey
interfaces to extend Destroyable.
-------------------------------------------------------------------
Changes to methods in the javax.security.auth.Destroyable interface
-------------------------------------------------------------------
/**
* Destroys this {@code Object}.
* Sensitive information associated with this {@code Object} is
* destroyed or cleared. Subsequent calls to methods on this
* {@code Object} will result in an {@code IllegalStateException}
* being thrown.
* <p>
* The default implementation throws {@code DestroyFailedException}.
*
* @exception DestroyFailedException if the destroy operation fails.
* @exception SecurityException if the caller does not have
* permission to destroy this {@code Object}.
*
* @since 1.8
*/
public default void destroy() throws DestroyFailedException { ... };
/**
* Determines if this {@code SecretKey} has been destroyed.
* <p>
* The default implementation returns false.
*
* @return true if this {@code SecretKey} has been destroyed,
* false otherwise.
*
* @since 1.8
*/
public default boolean isDestroyed() { ... };
--------------------------------------------------------------------
Changed class inheritance for the java.security.PrivateKey interface
--------------------------------------------------------------------
/**
* A private key.
* The purpose of this interface is to group (and provide type safety
* for) all private key interfaces.
* <p>
* Note: The specialized private key interfaces extend this interface.
* See, for example, the {@code DSAPrivateKey} interface in
* {@link java.security.interfaces}.
* <p>
* Implementations should override the default {@code destroy} and
* {@code isDestroyed} methods from the
* {@link javax.security.auth.Destroyable} interface to enable
* sensitive key information to be destroyed or cleared.
*
* @see Key
* @see PublicKey
* @see Certificate
* @see Signature#initVerify
* @see java.security.interfaces.DSAPrivateKey
* @see java.security.interfaces.RSAPrivateKey
* @see java.security.interfaces.RSAPrivateCrtKey
*
* @author Benjamin Renaud
* @author Josh Bloch
*/
public interface PrivateKey extends Key, Destroyable { ... }
------------------------------------------------------------------
Changed class inheritance for the javax.crypto.SecretKey interface
------------------------------------------------------------------
/**
* A secret (symmetric) key.
* The purpose of this interface is to group (and provide type safety
* for) all secret key interfaces.
* <p>
* Provider implementations of this interface must overwrite the
* {@code equals} and {@code hashCode} methods inherited from
* {@link java.lang.Object}, so that secret keys are compared based on
* their underlying key material and not based on reference.
* Implementations should also override the default {@code destroy} and
* {@code isDestroyed} methods from the
* {@link javax.security.auth.Destroyable} interface to enable
* sensitive key information to be destroyed or cleared.
*
* <p>Keys that implement this interface return the string {@code RAW}
* as their encoding format (see {@code getFormat}), and return the
* raw key bytes as the result of a {@code getEncoded} method call. (The
* {@code getFormat} and {@code getEncoded} methods are inherited
* from the {@link java.security.Key} parent interface.)
*
* @author Jan Luehe
*
* @see SecretKeyFactory
* @see Cipher
* @since 1.4
*/
public interface SecretKey extends Key, Destroyable { ... }
===========================================================
4. To support the logical grouping of keystores and entries
===========================================================
This involves defining an implementation of the
KeyStore.LoadStoreParameter interface that conveys the configuration
data that defines a keystore domain to the load and store methods
of KeyStore.
---------------------------------------------
New class in the java.security.KeyStore class
---------------------------------------------
/**
* Configuration data that specifies the collection of keystores in
* a keystore domain.
* It is used during {@code KeyStore}
* {@link #load(KeyStore.LoadStoreParameter) load} and
* {@link #store(KeyStore.LoadStoreParameter) store} operations.
* <p>
* The following syntax is supported for configuration data:
* <pre>
*
* domain <domainName> [<domainProperty> ...] {
* keystore <keystoreName> [<keystoreProperty> ...] ;
* ...
* };
* ...
*
* </pre>
* where {@code domainName} and {@code keystoreName} are strings
* enclosed in double quotes and
* {@code domainProperty} and {@code keystoreProperty} are key/value
* pairings.
* The key and value are strings separated by an 'equals' symbol and
* the value is enclosed in double quotes. A value may be either a
* printable string or a binary string of colon-separated pairs of
* hexadecimal digits.
* Multi-valued properties are represented as a comma-separated list of
* values, enclosed in square brackets. See {@link Arrays.toString}.
* <p>
* The following keystore properties are supported:
* <dl>
* <dt> {@code keyStoreType=<type>} </dt>
* <dd> The keystore type. </dd>
* <dt> {@code keyStoreURI=<uri>} </dt>
* <dd> The keystore location. </dd>
* </dl>
*
* <p>
* For example, configuration data for a simple keystore domain
* comprising three keystores is shown below:
* <pre>
*
* domain "app1" {
* keystore "truststore"
* keyStoreURI="file://app1/etc/truststore.jks"
*
* keystore "cacerts"
* keyStoreURI="${java.home}/lib/security/cacerts"
*
* keystore "keystore"
* keyStoreType="PKCS12"
* keyStoreURI="file://app1/etc/keystore.p12"
* };
*
* </pre>
* @since 1.8
*/
public final class DomainLoadStoreParameter implements
LoadStoreParameter {
/**
* Constructs a DomainLoadStoreParameter for a keystore domain with
* the parameters used to protect keystore data.
* The domain configuration data is identified by the supplied URI.
*
* @param configuration the domain configuration data
* @param protectionParams the parameters used to protect keystore
* data. It is cloned to prevent subsequent modification.
*
* @exception NullPointerExcetion if {@code configuration} or
* {@code protectionParams} is {@code null}
*/
public KeyStore.DomainLoadStoreParameter(URI configuration,
Map<String,ProtectionParameter> protectionParams) {...};
/**
* Gets the configuration data for this domain.
*
* @return the identifier for the domain's configuration data
*/
public URI getConfiguration() {...};
/**
* Gets the keystore protection parameters for keystores in this
* domain.
*
* @return an unmodifiable map of keystore names to protection
* parameters
*/
public Map<String,ProtectionParameter> getProtectionParams() {...};
/**
* Gets the keystore protection parameters for this domain.
* Keystore domains do not support a protection parameter.
*
* @return always returns {@code null}
*/
@Override
public KeyStore.ProtectionParameter getProtectionParameter() {...};
}
=============================================
5. To support the secure storage of passwords
=============================================
This involves introducing a new command option for the keytool utility
that accepts a password and stores it securely as a secret key.
--------------------------------------------------------------------
Addition to the keytool manpage for the new command: -importpassword
--------------------------------------------------------------------
-importpassword {-alias alias} [-keypass keypass]
{-storetype storetype}
{-keystore keystore} [-storepass storepass]
{-providerClass provider_class_name {-providerArg provider_arg}}
{-v} {-protected} {-Jjavaoption}
Imports a passphrase and stores it in a new KeyStore.SecretKeyEntry
identified by alias.
The passphrase may be supplied via the standard input stream;
otherwise the user is prompted for it.
keypass is a password used to protect the imported passphrase. If no
password is provided, the user is prompted for it. If you press
RETURN at the prompt, the key password is set to the same password
as that used for the keystore. keypass must be at least 6
characters long.
More information about the security-dev
mailing list