Path: blob/master/src/java.base/share/classes/java/security/KeyStore.java
41152 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.security;2627import java.io.*;28import java.security.cert.Certificate;29import java.security.cert.X509Certificate;30import java.security.cert.CertificateException;31import java.security.spec.AlgorithmParameterSpec;32import java.util.*;33import javax.crypto.SecretKey;3435import javax.security.auth.DestroyFailedException;36import javax.security.auth.callback.*;3738import sun.security.util.Debug;3940/**41* This class represents a storage facility for cryptographic42* keys and certificates.43*44* <p> A {@code KeyStore} manages different types of entries.45* Each type of entry implements the {@code KeyStore.Entry} interface.46* Three basic {@code KeyStore.Entry} implementations are provided:47*48* <ul>49* <li><b>KeyStore.PrivateKeyEntry</b>50* <p> This type of entry holds a cryptographic {@code PrivateKey},51* which is optionally stored in a protected format to prevent52* unauthorized access. It is also accompanied by a certificate chain53* for the corresponding public key.54*55* <p> Private keys and certificate chains are used by a given entity for56* self-authentication. Applications for this authentication include software57* distribution organizations which sign JAR files as part of releasing58* and/or licensing software.59*60* <li><b>KeyStore.SecretKeyEntry</b>61* <p> This type of entry holds a cryptographic {@code SecretKey},62* which is optionally stored in a protected format to prevent63* unauthorized access.64*65* <li><b>KeyStore.TrustedCertificateEntry</b>66* <p> This type of entry contains a single public key {@code Certificate}67* belonging to another party. It is called a <i>trusted certificate</i>68* because the keystore owner trusts that the public key in the certificate69* indeed belongs to the identity identified by the <i>subject</i> (owner)70* of the certificate.71*72* <p>This type of entry can be used to authenticate other parties.73* </ul>74*75* <p> Each entry in a keystore is identified by an "alias" string. In the76* case of private keys and their associated certificate chains, these strings77* distinguish among the different ways in which the entity may authenticate78* itself. For example, the entity may authenticate itself using different79* certificate authorities, or using different public key algorithms.80*81* <p> Whether aliases are case sensitive is implementation dependent. In order82* to avoid problems, it is recommended not to use aliases in a KeyStore that83* only differ in case.84*85* <p> Whether keystores are persistent, and the mechanisms used by the86* keystore if it is persistent, are not specified here. This allows87* use of a variety of techniques for protecting sensitive (e.g., private or88* secret) keys. Smart cards or other integrated cryptographic engines89* (SafeKeyper) are one option, and simpler mechanisms such as files may also90* be used (in a variety of formats).91*92* <p> Typical ways to request a KeyStore object include93* specifying an existing keystore file,94* relying on the default type and providing a specific keystore type.95*96* <ul>97* <li>To specify an existing keystore file:98* <pre>99* // get keystore password100* char[] password = getPassword();101*102* // probe the keystore file and load the keystore entries103* KeyStore ks = KeyStore.getInstance(new File("keyStoreName"), password);104*</pre>105* The system will probe the specified file to determine its keystore type106* and return a keystore implementation with its entries already loaded.107* When this approach is used there is no need to call the keystore's108* {@link #load(java.io.InputStream, char[]) load} method.109*110* <li>To rely on the default type:111* <pre>112* KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());113* </pre>114* The system will return a keystore implementation for the default type.115*116* <li>To provide a specific keystore type:117* <pre>118* KeyStore ks = KeyStore.getInstance("JKS");119* </pre>120* The system will return the most preferred implementation of the121* specified keystore type available in the environment.122* </ul>123*124* <p> Before a keystore can be accessed, it must be125* {@link #load(java.io.InputStream, char[]) loaded}126* (unless it was already loaded during instantiation).127* <pre>128* KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());129*130* // get user password and file input stream131* char[] password = getPassword();132*133* try (FileInputStream fis = new FileInputStream("keyStoreName")) {134* ks.load(fis, password);135* }136* </pre>137*138* To create an empty keystore using the above {@code load} method,139* pass {@code null} as the {@code InputStream} argument.140*141* <p> Once the keystore has been loaded, it is possible142* to read existing entries from the keystore, or to write new entries143* into the keystore:144* <pre>145* KeyStore.ProtectionParameter protParam =146* new KeyStore.PasswordProtection(password);147*148* // get my private key149* KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)150* ks.getEntry("privateKeyAlias", protParam);151* PrivateKey myPrivateKey = pkEntry.getPrivateKey();152*153* // save my secret key154* javax.crypto.SecretKey mySecretKey;155* KeyStore.SecretKeyEntry skEntry =156* new KeyStore.SecretKeyEntry(mySecretKey);157* ks.setEntry("secretKeyAlias", skEntry, protParam);158*159* // store away the keystore160* try (FileOutputStream fos = new FileOutputStream("newKeyStoreName")) {161* ks.store(fos, password);162* }163* </pre>164*165* Note that although the same password may be used to166* load the keystore, to protect the private key entry,167* to protect the secret key entry, and to store the keystore168* (as is shown in the sample code above),169* different passwords or other protection parameters170* may also be used.171*172* <p> Every implementation of the Java platform is required to support173* the following standard {@code KeyStore} type:174* <ul>175* <li>{@code PKCS12}</li>176* </ul>177* This type is described in the <a href=178* "{@docRoot}/../specs/security/standard-names.html#keystore-types">179* KeyStore section</a> of the180* Java Security Standard Algorithm Names Specification.181* Consult the release documentation for your implementation to see if any182* other types are supported.183*184* @author Jan Luehe185*186* @see java.security.PrivateKey187* @see javax.crypto.SecretKey188* @see java.security.cert.Certificate189*190* @since 1.2191*/192193public class KeyStore {194195private static final Debug kdebug = Debug.getInstance("keystore");196private static final Debug pdebug =197Debug.getInstance("provider", "Provider");198private static final boolean skipDebug =199Debug.isOn("engine=") && !Debug.isOn("keystore");200201/*202* Constant to lookup in the Security properties file to determine203* the default keystore type.204* In the Security properties file, the default keystore type is given as:205* <pre>206* keystore.type=jks207* </pre>208*/209private static final String KEYSTORE_TYPE = "keystore.type";210211// The keystore type212private String type;213214// The provider215private Provider provider;216217// The provider implementation218private KeyStoreSpi keyStoreSpi;219220// Has this keystore been initialized (loaded)?221private boolean initialized;222223/**224* A marker interface for {@code KeyStore}225* {@link #load(KeyStore.LoadStoreParameter) load}226* and227* {@link #store(KeyStore.LoadStoreParameter) store}228* parameters.229*230* @since 1.5231*/232public static interface LoadStoreParameter {233/**234* Gets the parameter used to protect keystore data.235*236* @return the parameter used to protect keystore data, or null237*/238public ProtectionParameter getProtectionParameter();239}240241/**242* A marker interface for keystore protection parameters.243*244* <p> The information stored in a {@code ProtectionParameter}245* object protects the contents of a keystore.246* For example, protection parameters may be used to check247* the integrity of keystore data, or to protect the248* confidentiality of sensitive keystore data249* (such as a {@code PrivateKey}).250*251* @since 1.5252*/253public static interface ProtectionParameter { }254255/**256* A password-based implementation of {@code ProtectionParameter}.257*258* @since 1.5259*/260public static class PasswordProtection implements261ProtectionParameter, javax.security.auth.Destroyable {262263private final char[] password;264private final String protectionAlgorithm;265private final AlgorithmParameterSpec protectionParameters;266private volatile boolean destroyed;267268/**269* Creates a password parameter.270*271* <p> The specified {@code password} is cloned before it is stored272* in the new {@code PasswordProtection} object.273*274* @param password the password, which may be {@code null}275*/276public PasswordProtection(char[] password) {277this.password = (password == null) ? null : password.clone();278this.protectionAlgorithm = null;279this.protectionParameters = null;280}281282/**283* Creates a password parameter and specifies the protection algorithm284* and associated parameters to use when encrypting a keystore entry.285* <p>286* The specified {@code password} is cloned before it is stored in the287* new {@code PasswordProtection} object.288*289* @param password the password, which may be {@code null}290* @param protectionAlgorithm the encryption algorithm name, for291* example, {@code PBEWithHmacSHA256AndAES_256}.292* See the Cipher section in the <a href=293* "{@docRoot}/../specs/security/standard-names.html#cipher-algorithm-names">294* Java Security Standard Algorithm Names Specification</a>295* for information about standard encryption algorithm names.296* @param protectionParameters the encryption algorithm parameter297* specification, which may be {@code null}298* @throws NullPointerException if {@code protectionAlgorithm} is299* {@code null}300*301* @since 1.8302*/303public PasswordProtection(char[] password, String protectionAlgorithm,304AlgorithmParameterSpec protectionParameters) {305if (protectionAlgorithm == null) {306throw new NullPointerException("invalid null input");307}308this.password = (password == null) ? null : password.clone();309this.protectionAlgorithm = protectionAlgorithm;310this.protectionParameters = protectionParameters;311}312313/**314* Gets the name of the protection algorithm.315* If none was set then the keystore provider will use its default316* protection algorithm.317*318* @return the algorithm name, or {@code null} if none was set319*320* @since 1.8321*/322public String getProtectionAlgorithm() {323return protectionAlgorithm;324}325326/**327* Gets the parameters supplied for the protection algorithm.328*329* @return the algorithm parameter specification, or {@code null},330* if none was set331*332* @since 1.8333*/334public AlgorithmParameterSpec getProtectionParameters() {335return protectionParameters;336}337338/**339* Gets the password.340*341* <p>Note that this method returns a reference to the password.342* If a clone of the array is created it is the caller's343* responsibility to zero out the password information344* after it is no longer needed.345*346* @see #destroy()347* @return the password, which may be {@code null}348* @throws IllegalStateException if the password has349* been cleared (destroyed)350*/351public synchronized char[] getPassword() {352if (destroyed) {353throw new IllegalStateException("password has been cleared");354}355return password;356}357358/**359* Clears the password.360*361* @throws DestroyFailedException if this method was unable362* to clear the password363*/364public synchronized void destroy() throws DestroyFailedException {365destroyed = true;366if (password != null) {367Arrays.fill(password, ' ');368}369}370371/**372* Determines if password has been cleared.373*374* @return true if the password has been cleared, false otherwise375*/376public synchronized boolean isDestroyed() {377return destroyed;378}379}380381/**382* A ProtectionParameter encapsulating a CallbackHandler.383*384* @since 1.5385*/386public static class CallbackHandlerProtection387implements ProtectionParameter {388389private final CallbackHandler handler;390391/**392* Constructs a new CallbackHandlerProtection from a393* CallbackHandler.394*395* @param handler the CallbackHandler396* @throws NullPointerException if handler is null397*/398public CallbackHandlerProtection(CallbackHandler handler) {399if (handler == null) {400throw new NullPointerException("handler must not be null");401}402this.handler = handler;403}404405/**406* Returns the CallbackHandler.407*408* @return the CallbackHandler.409*/410public CallbackHandler getCallbackHandler() {411return handler;412}413414}415416/**417* A marker interface for {@code KeyStore} entry types.418*419* @since 1.5420*/421public static interface Entry {422423/**424* Retrieves the attributes associated with an entry.425*426* @implSpec427* The default implementation returns an empty {@code Set}.428*429* @return an unmodifiable {@code Set} of attributes, possibly empty430*431* @since 1.8432*/433public default Set<Attribute> getAttributes() {434return Collections.<Attribute>emptySet();435}436437/**438* An attribute associated with a keystore entry.439* It comprises a name and one or more values.440*441* @since 1.8442*/443public interface Attribute {444/**445* Returns the attribute's name.446*447* @return the attribute name448*/449public String getName();450451/**452* Returns the attribute's value.453* Multi-valued attributes encode their values as a single string.454*455* @return the attribute value456*/457public String getValue();458}459}460461/**462* A {@code KeyStore} entry that holds a {@code PrivateKey}463* and corresponding certificate chain.464*465* @since 1.5466*/467public static final class PrivateKeyEntry implements Entry {468469private final PrivateKey privKey;470private final Certificate[] chain;471private final Set<Attribute> attributes;472473/**474* Constructs a {@code PrivateKeyEntry} with a475* {@code PrivateKey} and corresponding certificate chain.476*477* <p> The specified {@code chain} is cloned before it is stored478* in the new {@code PrivateKeyEntry} object.479*480* @param privateKey the {@code PrivateKey}481* @param chain an array of {@code Certificate}s482* representing the certificate chain.483* The chain must be ordered and contain a484* {@code Certificate} at index 0485* corresponding to the private key.486*487* @throws NullPointerException if488* {@code privateKey} or {@code chain}489* is {@code null}490* @throws IllegalArgumentException if the specified chain has a491* length of 0, if the specified chain does not contain492* {@code Certificate}s of the same type,493* or if the {@code PrivateKey} algorithm494* does not match the algorithm of the {@code PublicKey}495* in the end entity {@code Certificate} (at index 0)496*/497public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain) {498this(privateKey, chain, Collections.<Attribute>emptySet());499}500501/**502* Constructs a {@code PrivateKeyEntry} with a {@code PrivateKey} and503* corresponding certificate chain and associated entry attributes.504*505* <p> The specified {@code chain} and {@code attributes} are cloned506* before they are stored in the new {@code PrivateKeyEntry} object.507*508* @param privateKey the {@code PrivateKey}509* @param chain an array of {@code Certificate}s510* representing the certificate chain.511* The chain must be ordered and contain a512* {@code Certificate} at index 0513* corresponding to the private key.514* @param attributes the attributes515*516* @throws NullPointerException if {@code privateKey}, {@code chain}517* or {@code attributes} is {@code null}518* @throws IllegalArgumentException if the specified chain has a519* length of 0, if the specified chain does not contain520* {@code Certificate}s of the same type,521* or if the {@code PrivateKey} algorithm522* does not match the algorithm of the {@code PublicKey}523* in the end entity {@code Certificate} (at index 0)524*525* @since 1.8526*/527public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain,528Set<Attribute> attributes) {529530if (privateKey == null || chain == null || attributes == null) {531throw new NullPointerException("invalid null input");532}533if (chain.length == 0) {534throw new IllegalArgumentException535("invalid zero-length input chain");536}537538Certificate[] clonedChain = chain.clone();539String certType = clonedChain[0].getType();540for (int i = 1; i < clonedChain.length; i++) {541if (!certType.equals(clonedChain[i].getType())) {542throw new IllegalArgumentException543("chain does not contain certificates " +544"of the same type");545}546}547if (!privateKey.getAlgorithm().equals548(clonedChain[0].getPublicKey().getAlgorithm())) {549throw new IllegalArgumentException550("private key algorithm does not match " +551"algorithm of public key in end entity " +552"certificate (at index 0)");553}554this.privKey = privateKey;555556if (clonedChain[0] instanceof X509Certificate &&557!(clonedChain instanceof X509Certificate[])) {558559this.chain = new X509Certificate[clonedChain.length];560System.arraycopy(clonedChain, 0,561this.chain, 0, clonedChain.length);562} else {563this.chain = clonedChain;564}565566this.attributes =567Collections.unmodifiableSet(new HashSet<>(attributes));568}569570/**571* Gets the {@code PrivateKey} from this entry.572*573* @return the {@code PrivateKey} from this entry574*/575public PrivateKey getPrivateKey() {576return privKey;577}578579/**580* Gets the {@code Certificate} chain from this entry.581*582* <p> The stored chain is cloned before being returned.583*584* @return an array of {@code Certificate}s corresponding585* to the certificate chain for the public key.586* If the certificates are of type X.509,587* the runtime type of the returned array is588* {@code X509Certificate[]}.589*/590public Certificate[] getCertificateChain() {591return chain.clone();592}593594/**595* Gets the end entity {@code Certificate}596* from the certificate chain in this entry.597*598* @return the end entity {@code Certificate} (at index 0)599* from the certificate chain in this entry.600* If the certificate is of type X.509,601* the runtime type of the returned certificate is602* {@code X509Certificate}.603*/604public Certificate getCertificate() {605return chain[0];606}607608/**609* Retrieves the attributes associated with an entry.610*611* @return an unmodifiable {@code Set} of attributes, possibly empty612*613* @since 1.8614*/615@Override616public Set<Attribute> getAttributes() {617return attributes;618}619620/**621* Returns a string representation of this PrivateKeyEntry.622* @return a string representation of this PrivateKeyEntry.623*/624public String toString() {625StringBuilder sb = new StringBuilder();626sb.append("Private key entry and certificate chain with "627+ chain.length + " elements:\r\n");628for (Certificate cert : chain) {629sb.append(cert);630sb.append("\r\n");631}632return sb.toString();633}634635}636637/**638* A {@code KeyStore} entry that holds a {@code SecretKey}.639*640* @since 1.5641*/642public static final class SecretKeyEntry implements Entry {643644private final SecretKey sKey;645private final Set<Attribute> attributes;646647/**648* Constructs a {@code SecretKeyEntry} with a649* {@code SecretKey}.650*651* @param secretKey the {@code SecretKey}652*653* @throws NullPointerException if {@code secretKey}654* is {@code null}655*/656public SecretKeyEntry(SecretKey secretKey) {657if (secretKey == null) {658throw new NullPointerException("invalid null input");659}660this.sKey = secretKey;661this.attributes = Collections.<Attribute>emptySet();662}663664/**665* Constructs a {@code SecretKeyEntry} with a {@code SecretKey} and666* associated entry attributes.667*668* <p> The specified {@code attributes} is cloned before it is stored669* in the new {@code SecretKeyEntry} object.670*671* @param secretKey the {@code SecretKey}672* @param attributes the attributes673*674* @throws NullPointerException if {@code secretKey} or675* {@code attributes} is {@code null}676*677* @since 1.8678*/679public SecretKeyEntry(SecretKey secretKey, Set<Attribute> attributes) {680681if (secretKey == null || attributes == null) {682throw new NullPointerException("invalid null input");683}684this.sKey = secretKey;685this.attributes =686Collections.unmodifiableSet(new HashSet<>(attributes));687}688689/**690* Gets the {@code SecretKey} from this entry.691*692* @return the {@code SecretKey} from this entry693*/694public SecretKey getSecretKey() {695return sKey;696}697698/**699* Retrieves the attributes associated with an entry.700*701* @return an unmodifiable {@code Set} of attributes, possibly empty702*703* @since 1.8704*/705@Override706public Set<Attribute> getAttributes() {707return attributes;708}709710/**711* Returns a string representation of this SecretKeyEntry.712* @return a string representation of this SecretKeyEntry.713*/714public String toString() {715return "Secret key entry with algorithm " + sKey.getAlgorithm();716}717}718719/**720* A {@code KeyStore} entry that holds a trusted721* {@code Certificate}.722*723* @since 1.5724*/725public static final class TrustedCertificateEntry implements Entry {726727private final Certificate cert;728private final Set<Attribute> attributes;729730/**731* Constructs a {@code TrustedCertificateEntry} with a732* trusted {@code Certificate}.733*734* @param trustedCert the trusted {@code Certificate}735*736* @throws NullPointerException if737* {@code trustedCert} is {@code null}738*/739public TrustedCertificateEntry(Certificate trustedCert) {740if (trustedCert == null) {741throw new NullPointerException("invalid null input");742}743this.cert = trustedCert;744this.attributes = Collections.<Attribute>emptySet();745}746747/**748* Constructs a {@code TrustedCertificateEntry} with a749* trusted {@code Certificate} and associated entry attributes.750*751* <p> The specified {@code attributes} is cloned before it is stored752* in the new {@code TrustedCertificateEntry} object.753*754* @param trustedCert the trusted {@code Certificate}755* @param attributes the attributes756*757* @throws NullPointerException if {@code trustedCert} or758* {@code attributes} is {@code null}759*760* @since 1.8761*/762public TrustedCertificateEntry(Certificate trustedCert,763Set<Attribute> attributes) {764if (trustedCert == null || attributes == null) {765throw new NullPointerException("invalid null input");766}767this.cert = trustedCert;768this.attributes =769Collections.unmodifiableSet(new HashSet<>(attributes));770}771772/**773* Gets the trusted {@code Certficate} from this entry.774*775* @return the trusted {@code Certificate} from this entry776*/777public Certificate getTrustedCertificate() {778return cert;779}780781/**782* Retrieves the attributes associated with an entry.783*784* @return an unmodifiable {@code Set} of attributes, possibly empty785*786* @since 1.8787*/788@Override789public Set<Attribute> getAttributes() {790return attributes;791}792793/**794* Returns a string representation of this TrustedCertificateEntry.795* @return a string representation of this TrustedCertificateEntry.796*/797public String toString() {798return "Trusted certificate entry:\r\n" + cert.toString();799}800}801802/**803* Creates a KeyStore object of the given type, and encapsulates the given804* provider implementation (SPI object) in it.805*806* @param keyStoreSpi the provider implementation.807* @param provider the provider.808* @param type the keystore type.809*/810protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)811{812this.keyStoreSpi = keyStoreSpi;813this.provider = provider;814this.type = type;815816if (!skipDebug && pdebug != null) {817pdebug.println("KeyStore." + type.toUpperCase() + " type from: " +818getProviderName());819}820}821822private String getProviderName() {823return (provider == null) ? "(no provider)" : provider.getName();824}825826/**827* Returns a keystore object of the specified type.828*829* <p> This method traverses the list of registered security Providers,830* starting with the most preferred Provider.831* A new KeyStore object encapsulating the832* KeyStoreSpi implementation from the first833* Provider that supports the specified type is returned.834*835* <p> Note that the list of registered providers may be retrieved via836* the {@link Security#getProviders() Security.getProviders()} method.837*838* @implNote839* The JDK Reference Implementation additionally uses the840* {@code jdk.security.provider.preferred}841* {@link Security#getProperty(String) Security} property to determine842* the preferred provider order for the specified algorithm. This843* may be different than the order of providers returned by844* {@link Security#getProviders() Security.getProviders()}.845*846* @param type the type of keystore.847* See the KeyStore section in the <a href=848* "{@docRoot}/../specs/security/standard-names.html#keystore-types">849* Java Security Standard Algorithm Names Specification</a>850* for information about standard keystore types.851*852* @return a keystore object of the specified type853*854* @throws KeyStoreException if no {@code Provider} supports a855* {@code KeyStoreSpi} implementation for the856* specified type857*858* @throws NullPointerException if {@code type} is {@code null}859*860* @see Provider861*/862public static KeyStore getInstance(String type)863throws KeyStoreException864{865Objects.requireNonNull(type, "null type name");866try {867Object[] objs = Security.getImpl(type, "KeyStore", (String)null);868return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);869} catch (NoSuchAlgorithmException nsae) {870throw new KeyStoreException(type + " not found", nsae);871} catch (NoSuchProviderException nspe) {872throw new KeyStoreException(type + " not found", nspe);873}874}875876/**877* Returns a keystore object of the specified type.878*879* <p> A new KeyStore object encapsulating the880* KeyStoreSpi implementation from the specified provider881* is returned. The specified provider must be registered882* in the security provider list.883*884* <p> Note that the list of registered providers may be retrieved via885* the {@link Security#getProviders() Security.getProviders()} method.886*887* @param type the type of keystore.888* See the KeyStore section in the <a href=889* "{@docRoot}/../specs/security/standard-names.html#keystore-types">890* Java Security Standard Algorithm Names Specification</a>891* for information about standard keystore types.892*893* @param provider the name of the provider.894*895* @return a keystore object of the specified type896*897* @throws IllegalArgumentException if the provider name is {@code null}898* or empty899*900* @throws KeyStoreException if a {@code KeyStoreSpi}901* implementation for the specified type is not902* available from the specified provider903*904* @throws NoSuchProviderException if the specified provider is not905* registered in the security provider list906*907* @throws NullPointerException if {@code type} is {@code null}908*909* @see Provider910*/911public static KeyStore getInstance(String type, String provider)912throws KeyStoreException, NoSuchProviderException913{914Objects.requireNonNull(type, "null type name");915if (provider == null || provider.isEmpty())916throw new IllegalArgumentException("missing provider");917try {918Object[] objs = Security.getImpl(type, "KeyStore", provider);919return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);920} catch (NoSuchAlgorithmException nsae) {921throw new KeyStoreException(type + " not found", nsae);922}923}924925/**926* Returns a keystore object of the specified type.927*928* <p> A new KeyStore object encapsulating the929* KeyStoreSpi implementation from the specified Provider930* object is returned. Note that the specified Provider object931* does not have to be registered in the provider list.932*933* @param type the type of keystore.934* See the KeyStore section in the <a href=935* "{@docRoot}/../specs/security/standard-names.html#keystore-types">936* Java Security Standard Algorithm Names Specification</a>937* for information about standard keystore types.938*939* @param provider the provider.940*941* @return a keystore object of the specified type942*943* @throws IllegalArgumentException if the specified provider is944* {@code null}945*946* @throws KeyStoreException if {@code KeyStoreSpi}947* implementation for the specified type is not available948* from the specified {@code Provider} object949*950* @throws NullPointerException if {@code type} is {@code null}951*952* @see Provider953*954* @since 1.4955*/956public static KeyStore getInstance(String type, Provider provider)957throws KeyStoreException958{959Objects.requireNonNull(type, "null type name");960if (provider == null)961throw new IllegalArgumentException("missing provider");962try {963Object[] objs = Security.getImpl(type, "KeyStore", provider);964return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);965} catch (NoSuchAlgorithmException nsae) {966throw new KeyStoreException(type + " not found", nsae);967}968}969970/**971* Returns the default keystore type as specified by the972* {@code keystore.type} security property, or the string973* {@literal "jks"} (acronym for {@literal "Java keystore"})974* if no such property exists.975*976* <p>The default keystore type can be used by applications that do not977* want to use a hard-coded keystore type when calling one of the978* {@code getInstance} methods, and want to provide a default keystore979* type in case a user does not specify its own.980*981* <p>The default keystore type can be changed by setting the value of the982* {@code keystore.type} security property to the desired keystore type.983*984* @return the default keystore type as specified by the985* {@code keystore.type} security property, or the string {@literal "jks"}986* if no such property exists.987* @see java.security.Security security properties988*/989public static final String getDefaultType() {990@SuppressWarnings("removal")991String kstype = AccessController.doPrivileged(new PrivilegedAction<>() {992public String run() {993return Security.getProperty(KEYSTORE_TYPE);994}995});996if (kstype == null) {997kstype = "jks";998}999return kstype;1000}10011002/**1003* Returns the provider of this keystore.1004*1005* @return the provider of this keystore.1006*/1007public final Provider getProvider()1008{1009return this.provider;1010}10111012/**1013* Returns the type of this keystore.1014*1015* @return the type of this keystore.1016*/1017public final String getType()1018{1019return this.type;1020}10211022/**1023* Returns the key associated with the given alias, using the given1024* password to recover it. The key must have been associated with1025* the alias by a call to {@code setKeyEntry},1026* or by a call to {@code setEntry} with a1027* {@code PrivateKeyEntry} or {@code SecretKeyEntry}.1028*1029* @param alias the alias name1030* @param password the password for recovering the key1031*1032* @return the requested key, or null if the given alias does not exist1033* or does not identify a key-related entry.1034*1035* @throws KeyStoreException if the keystore has not been initialized1036* (loaded).1037* @throws NoSuchAlgorithmException if the algorithm for recovering the1038* key cannot be found1039* @throws UnrecoverableKeyException if the key cannot be recovered1040* (e.g., the given password is wrong).1041*/1042public final Key getKey(String alias, char[] password)1043throws KeyStoreException, NoSuchAlgorithmException,1044UnrecoverableKeyException1045{1046if (!initialized) {1047throw new KeyStoreException("Uninitialized keystore");1048}1049return keyStoreSpi.engineGetKey(alias, password);1050}10511052/**1053* Returns the certificate chain associated with the given alias.1054* The certificate chain must have been associated with the alias1055* by a call to {@code setKeyEntry},1056* or by a call to {@code setEntry} with a1057* {@code PrivateKeyEntry}.1058*1059* @param alias the alias name1060*1061* @return the certificate chain (ordered with the user's certificate first1062* followed by zero or more certificate authorities), or null if the given alias1063* does not exist or does not contain a certificate chain1064*1065* @throws KeyStoreException if the keystore has not been initialized1066* (loaded).1067*/1068public final Certificate[] getCertificateChain(String alias)1069throws KeyStoreException1070{1071if (!initialized) {1072throw new KeyStoreException("Uninitialized keystore");1073}1074return keyStoreSpi.engineGetCertificateChain(alias);1075}10761077/**1078* Returns the certificate associated with the given alias.1079*1080* <p> If the given alias name identifies an entry1081* created by a call to {@code setCertificateEntry},1082* or created by a call to {@code setEntry} with a1083* {@code TrustedCertificateEntry},1084* then the trusted certificate contained in that entry is returned.1085*1086* <p> If the given alias name identifies an entry1087* created by a call to {@code setKeyEntry},1088* or created by a call to {@code setEntry} with a1089* {@code PrivateKeyEntry},1090* then the first element of the certificate chain in that entry1091* is returned.1092*1093* @param alias the alias name1094*1095* @return the certificate, or null if the given alias does not exist or1096* does not contain a certificate.1097*1098* @throws KeyStoreException if the keystore has not been initialized1099* (loaded).1100*/1101public final Certificate getCertificate(String alias)1102throws KeyStoreException1103{1104if (!initialized) {1105throw new KeyStoreException("Uninitialized keystore");1106}1107return keyStoreSpi.engineGetCertificate(alias);1108}11091110/**1111* Returns the creation date of the entry identified by the given alias.1112*1113* @param alias the alias name1114*1115* @return the creation date of this entry, or null if the given alias does1116* not exist1117*1118* @throws KeyStoreException if the keystore has not been initialized1119* (loaded).1120*/1121public final Date getCreationDate(String alias)1122throws KeyStoreException1123{1124if (!initialized) {1125throw new KeyStoreException("Uninitialized keystore");1126}1127return keyStoreSpi.engineGetCreationDate(alias);1128}11291130/**1131* Assigns the given key to the given alias, protecting it with the given1132* password.1133*1134* <p>If the given key is of type {@code java.security.PrivateKey},1135* it must be accompanied by a certificate chain certifying the1136* corresponding public key.1137*1138* <p>If the given alias already exists, the keystore information1139* associated with it is overridden by the given key (and possibly1140* certificate chain).1141*1142* @param alias the alias name1143* @param key the key to be associated with the alias1144* @param password the password to protect the key1145* @param chain the certificate chain for the corresponding public1146* key (only required if the given key is of type1147* {@code java.security.PrivateKey}).1148*1149* @throws KeyStoreException if the keystore has not been initialized1150* (loaded), the given key cannot be protected, or this operation fails1151* for some other reason1152*/1153public final void setKeyEntry(String alias, Key key, char[] password,1154Certificate[] chain)1155throws KeyStoreException1156{1157if (!initialized) {1158throw new KeyStoreException("Uninitialized keystore");1159}1160if ((key instanceof PrivateKey) &&1161(chain == null || chain.length == 0)) {1162throw new IllegalArgumentException("Private key must be "1163+ "accompanied by certificate "1164+ "chain");1165}1166keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);1167}11681169/**1170* Assigns the given key (that has already been protected) to the given1171* alias.1172*1173* <p>If the protected key is of type1174* {@code java.security.PrivateKey}, it must be accompanied by a1175* certificate chain certifying the corresponding public key. If the1176* underlying keystore implementation is of type {@code jks},1177* {@code key} must be encoded as an1178* {@code EncryptedPrivateKeyInfo} as defined in the PKCS #8 standard.1179*1180* <p>If the given alias already exists, the keystore information1181* associated with it is overridden by the given key (and possibly1182* certificate chain).1183*1184* @param alias the alias name1185* @param key the key (in protected format) to be associated with the alias1186* @param chain the certificate chain for the corresponding public1187* key (only useful if the protected key is of type1188* {@code java.security.PrivateKey}).1189*1190* @throws KeyStoreException if the keystore has not been initialized1191* (loaded), or if this operation fails for some other reason.1192*/1193public final void setKeyEntry(String alias, byte[] key,1194Certificate[] chain)1195throws KeyStoreException1196{1197if (!initialized) {1198throw new KeyStoreException("Uninitialized keystore");1199}1200keyStoreSpi.engineSetKeyEntry(alias, key, chain);1201}12021203/**1204* Assigns the given trusted certificate to the given alias.1205*1206* <p> If the given alias identifies an existing entry1207* created by a call to {@code setCertificateEntry},1208* or created by a call to {@code setEntry} with a1209* {@code TrustedCertificateEntry},1210* the trusted certificate in the existing entry1211* is overridden by the given certificate.1212*1213* @param alias the alias name1214* @param cert the certificate1215*1216* @throws KeyStoreException if the keystore has not been initialized,1217* or the given alias already exists and does not identify an1218* entry containing a trusted certificate,1219* or this operation fails for some other reason.1220*/1221public final void setCertificateEntry(String alias, Certificate cert)1222throws KeyStoreException1223{1224if (!initialized) {1225throw new KeyStoreException("Uninitialized keystore");1226}1227keyStoreSpi.engineSetCertificateEntry(alias, cert);1228}12291230/**1231* Deletes the entry identified by the given alias from this keystore.1232*1233* @param alias the alias name1234*1235* @throws KeyStoreException if the keystore has not been initialized,1236* or if the entry cannot be removed.1237*/1238public final void deleteEntry(String alias)1239throws KeyStoreException1240{1241if (!initialized) {1242throw new KeyStoreException("Uninitialized keystore");1243}1244keyStoreSpi.engineDeleteEntry(alias);1245}12461247/**1248* Lists all the alias names of this keystore.1249*1250* @return enumeration of the alias names1251*1252* @throws KeyStoreException if the keystore has not been initialized1253* (loaded).1254*/1255public final Enumeration<String> aliases()1256throws KeyStoreException1257{1258if (!initialized) {1259throw new KeyStoreException("Uninitialized keystore");1260}1261return keyStoreSpi.engineAliases();1262}12631264/**1265* Checks if the given alias exists in this keystore.1266*1267* @param alias the alias name1268*1269* @return true if the alias exists, false otherwise1270*1271* @throws KeyStoreException if the keystore has not been initialized1272* (loaded).1273*/1274public final boolean containsAlias(String alias)1275throws KeyStoreException1276{1277if (!initialized) {1278throw new KeyStoreException("Uninitialized keystore");1279}1280return keyStoreSpi.engineContainsAlias(alias);1281}12821283/**1284* Retrieves the number of entries in this keystore.1285*1286* @return the number of entries in this keystore1287*1288* @throws KeyStoreException if the keystore has not been initialized1289* (loaded).1290*/1291public final int size()1292throws KeyStoreException1293{1294if (!initialized) {1295throw new KeyStoreException("Uninitialized keystore");1296}1297return keyStoreSpi.engineSize();1298}12991300/**1301* Returns true if the entry identified by the given alias1302* was created by a call to {@code setKeyEntry},1303* or created by a call to {@code setEntry} with a1304* {@code PrivateKeyEntry} or a {@code SecretKeyEntry}.1305*1306* @param alias the alias for the keystore entry to be checked1307*1308* @return true if the entry identified by the given alias is a1309* key-related entry, false otherwise.1310*1311* @throws KeyStoreException if the keystore has not been initialized1312* (loaded).1313*/1314public final boolean isKeyEntry(String alias)1315throws KeyStoreException1316{1317if (!initialized) {1318throw new KeyStoreException("Uninitialized keystore");1319}1320return keyStoreSpi.engineIsKeyEntry(alias);1321}13221323/**1324* Returns true if the entry identified by the given alias1325* was created by a call to {@code setCertificateEntry},1326* or created by a call to {@code setEntry} with a1327* {@code TrustedCertificateEntry}.1328*1329* @param alias the alias for the keystore entry to be checked1330*1331* @return true if the entry identified by the given alias contains a1332* trusted certificate, false otherwise.1333*1334* @throws KeyStoreException if the keystore has not been initialized1335* (loaded).1336*/1337public final boolean isCertificateEntry(String alias)1338throws KeyStoreException1339{1340if (!initialized) {1341throw new KeyStoreException("Uninitialized keystore");1342}1343return keyStoreSpi.engineIsCertificateEntry(alias);1344}13451346/**1347* Returns the (alias) name of the first keystore entry whose certificate1348* matches the given certificate.1349*1350* <p> This method attempts to match the given certificate with each1351* keystore entry. If the entry being considered was1352* created by a call to {@code setCertificateEntry},1353* or created by a call to {@code setEntry} with a1354* {@code TrustedCertificateEntry},1355* then the given certificate is compared to that entry's certificate.1356*1357* <p> If the entry being considered was1358* created by a call to {@code setKeyEntry},1359* or created by a call to {@code setEntry} with a1360* {@code PrivateKeyEntry},1361* then the given certificate is compared to the first1362* element of that entry's certificate chain.1363*1364* @param cert the certificate to match with.1365*1366* @return the alias name of the first entry with a matching certificate,1367* or null if no such entry exists in this keystore.1368*1369* @throws KeyStoreException if the keystore has not been initialized1370* (loaded).1371*/1372public final String getCertificateAlias(Certificate cert)1373throws KeyStoreException1374{1375if (!initialized) {1376throw new KeyStoreException("Uninitialized keystore");1377}1378return keyStoreSpi.engineGetCertificateAlias(cert);1379}13801381/**1382* Stores this keystore to the given output stream, and protects its1383* integrity with the given password.1384*1385* @param stream the output stream to which this keystore is written.1386* @param password the password to generate the keystore integrity check1387*1388* @throws KeyStoreException if the keystore has not been initialized1389* (loaded).1390* @throws IOException if there was an I/O problem with data1391* @throws NoSuchAlgorithmException if the appropriate data integrity1392* algorithm could not be found1393* @throws CertificateException if any of the certificates included in1394* the keystore data could not be stored1395*/1396public final void store(OutputStream stream, char[] password)1397throws KeyStoreException, IOException, NoSuchAlgorithmException,1398CertificateException1399{1400if (!initialized) {1401throw new KeyStoreException("Uninitialized keystore");1402}1403keyStoreSpi.engineStore(stream, password);1404}14051406/**1407* Stores this keystore using the given {@code LoadStoreParameter}.1408*1409* @param param the {@code LoadStoreParameter}1410* that specifies how to store the keystore,1411* which may be {@code null}1412*1413* @throws IllegalArgumentException if the given1414* {@code LoadStoreParameter}1415* input is not recognized1416* @throws KeyStoreException if the keystore has not been initialized1417* (loaded)1418* @throws IOException if there was an I/O problem with data1419* @throws NoSuchAlgorithmException if the appropriate data integrity1420* algorithm could not be found1421* @throws CertificateException if any of the certificates included in1422* the keystore data could not be stored1423* @throws UnsupportedOperationException if this operation is not supported1424*1425* @since 1.51426*/1427public final void store(LoadStoreParameter param)1428throws KeyStoreException, IOException,1429NoSuchAlgorithmException, CertificateException {1430if (!initialized) {1431throw new KeyStoreException("Uninitialized keystore");1432}1433keyStoreSpi.engineStore(param);1434}14351436/**1437* Loads this KeyStore from the given input stream.1438*1439* <p>A password may be given to unlock the keystore1440* (e.g. the keystore resides on a hardware token device),1441* or to check the integrity of the keystore data.1442* If a password is not given for integrity checking,1443* then integrity checking is not performed.1444*1445* <p>In order to create an empty keystore, or if the keystore cannot1446* be initialized from a stream, pass {@code null}1447* as the {@code stream} argument.1448*1449* <p> Note that if this keystore has already been loaded, it is1450* reinitialized and loaded again from the given input stream.1451*1452* @param stream the input stream from which the keystore is loaded,1453* or {@code null}1454* @param password the password used to check the integrity of1455* the keystore, the password used to unlock the keystore,1456* or {@code null}1457*1458* @throws IOException if there is an I/O or format problem with the1459* keystore data, if a password is required but not given,1460* or if the given password was incorrect. If the error is due to a1461* wrong password, the {@link Throwable#getCause cause} of the1462* {@code IOException} should be an1463* {@code UnrecoverableKeyException}1464* @throws NoSuchAlgorithmException if the algorithm used to check1465* the integrity of the keystore cannot be found1466* @throws CertificateException if any of the certificates in the1467* keystore could not be loaded1468*/1469public final void load(InputStream stream, char[] password)1470throws IOException, NoSuchAlgorithmException, CertificateException1471{1472keyStoreSpi.engineLoad(stream, password);1473initialized = true;1474}14751476/**1477* Loads this keystore using the given {@code LoadStoreParameter}.1478*1479* <p> Note that if this KeyStore has already been loaded, it is1480* reinitialized and loaded again from the given parameter.1481*1482* @param param the {@code LoadStoreParameter}1483* that specifies how to load the keystore,1484* which may be {@code null}1485*1486* @throws IllegalArgumentException if the given1487* {@code LoadStoreParameter}1488* input is not recognized1489* @throws IOException if there is an I/O or format problem with the1490* keystore data. If the error is due to an incorrect1491* {@code ProtectionParameter} (e.g. wrong password)1492* the {@link Throwable#getCause cause} of the1493* {@code IOException} should be an1494* {@code UnrecoverableKeyException}1495* @throws NoSuchAlgorithmException if the algorithm used to check1496* the integrity of the keystore cannot be found1497* @throws CertificateException if any of the certificates in the1498* keystore could not be loaded1499*1500* @since 1.51501*/1502public final void load(LoadStoreParameter param)1503throws IOException, NoSuchAlgorithmException,1504CertificateException {15051506keyStoreSpi.engineLoad(param);1507initialized = true;1508}15091510/**1511* Gets a keystore {@code Entry} for the specified alias1512* with the specified protection parameter.1513*1514* @param alias get the keystore {@code Entry} for this alias1515* @param protParam the {@code ProtectionParameter}1516* used to protect the {@code Entry},1517* which may be {@code null}1518*1519* @return the keystore {@code Entry} for the specified alias,1520* or {@code null} if there is no such entry1521*1522* @throws NullPointerException if1523* {@code alias} is {@code null}1524* @throws NoSuchAlgorithmException if the algorithm for recovering the1525* entry cannot be found1526* @throws UnrecoverableEntryException if the specified1527* {@code protParam} were insufficient or invalid1528* @throws UnrecoverableKeyException if the entry is a1529* {@code PrivateKeyEntry} or {@code SecretKeyEntry}1530* and the specified {@code protParam} does not contain1531* the information needed to recover the key (e.g. wrong password)1532* @throws KeyStoreException if the keystore has not been initialized1533* (loaded).1534* @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter)1535*1536* @since 1.51537*/1538public final Entry getEntry(String alias, ProtectionParameter protParam)1539throws NoSuchAlgorithmException, UnrecoverableEntryException,1540KeyStoreException {15411542if (alias == null) {1543throw new NullPointerException("invalid null input");1544}1545if (!initialized) {1546throw new KeyStoreException("Uninitialized keystore");1547}1548return keyStoreSpi.engineGetEntry(alias, protParam);1549}15501551/**1552* Saves a keystore {@code Entry} under the specified alias.1553* The protection parameter is used to protect the1554* {@code Entry}.1555*1556* <p> If an entry already exists for the specified alias,1557* it is overridden.1558*1559* @param alias save the keystore {@code Entry} under this alias1560* @param entry the {@code Entry} to save1561* @param protParam the {@code ProtectionParameter}1562* used to protect the {@code Entry},1563* which may be {@code null}1564*1565* @throws NullPointerException if1566* {@code alias} or {@code entry}1567* is {@code null}1568* @throws KeyStoreException if the keystore has not been initialized1569* (loaded), or if this operation fails for some other reason1570*1571* @see #getEntry(String, KeyStore.ProtectionParameter)1572*1573* @since 1.51574*/1575public final void setEntry(String alias, Entry entry,1576ProtectionParameter protParam)1577throws KeyStoreException {1578if (alias == null || entry == null) {1579throw new NullPointerException("invalid null input");1580}1581if (!initialized) {1582throw new KeyStoreException("Uninitialized keystore");1583}1584keyStoreSpi.engineSetEntry(alias, entry, protParam);1585}15861587/**1588* Determines if the keystore {@code Entry} for the specified1589* {@code alias} is an instance or subclass of the specified1590* {@code entryClass}.1591*1592* @param alias the alias name1593* @param entryClass the entry class1594*1595* @return true if the keystore {@code Entry} for the specified1596* {@code alias} is an instance or subclass of the1597* specified {@code entryClass}, false otherwise1598*1599* @throws NullPointerException if1600* {@code alias} or {@code entryClass}1601* is {@code null}1602* @throws KeyStoreException if the keystore has not been1603* initialized (loaded)1604*1605* @since 1.51606*/1607public final boolean1608entryInstanceOf(String alias,1609Class<? extends KeyStore.Entry> entryClass)1610throws KeyStoreException1611{16121613if (alias == null || entryClass == null) {1614throw new NullPointerException("invalid null input");1615}1616if (!initialized) {1617throw new KeyStoreException("Uninitialized keystore");1618}1619return keyStoreSpi.engineEntryInstanceOf(alias, entryClass);1620}16211622/**1623* Returns a loaded keystore object of the appropriate keystore type.1624* First the keystore type is determined by probing the specified file.1625* Then a keystore object is instantiated and loaded using the data from1626* that file.1627*1628* <p>1629* A password may be given to unlock the keystore1630* (e.g. the keystore resides on a hardware token device),1631* or to check the integrity of the keystore data.1632* If a password is not given for integrity checking,1633* then integrity checking is not performed.1634*1635* <p>1636* This method traverses the list of registered security1637* {@linkplain Provider providers}, starting with the most1638* preferred Provider.1639* For each {@link KeyStoreSpi} implementation supported by a1640* Provider, it invokes the {@link1641* KeyStoreSpi#engineProbe(InputStream) engineProbe} method to1642* determine if it supports the specified keystore.1643* A new KeyStore object is returned that encapsulates the KeyStoreSpi1644* implementation from the first Provider that supports the specified file.1645*1646* <p> Note that the list of registered providers may be retrieved via1647* the {@link Security#getProviders() Security.getProviders()} method.1648*1649* @param file the keystore file1650* @param password the keystore password, which may be {@code null}1651*1652* @return a keystore object loaded with keystore data1653*1654* @throws KeyStoreException if no Provider supports a KeyStoreSpi1655* implementation for the specified keystore file.1656* @throws IOException if there is an I/O or format problem with the1657* keystore data, if a password is required but not given,1658* or if the given password was incorrect. If the error is1659* due to a wrong password, the {@link Throwable#getCause cause}1660* of the {@code IOException} should be an1661* {@code UnrecoverableKeyException}.1662* @throws NoSuchAlgorithmException if the algorithm used to check the1663* integrity of the keystore cannot be found.1664* @throws CertificateException if any of the certificates in the1665* keystore could not be loaded.1666* @throws IllegalArgumentException if file does not exist or does not1667* refer to a normal file.1668* @throws NullPointerException if file is {@code null}.1669* @throws SecurityException if a security manager exists and its1670* {@link java.lang.SecurityManager#checkRead} method denies1671* read access to the specified file.1672*1673* @see Provider1674*1675* @since 91676*/1677public static final KeyStore getInstance(File file, char[] password)1678throws KeyStoreException, IOException, NoSuchAlgorithmException,1679CertificateException {1680return getInstance(file, password, null, true);1681}16821683/**1684* Returns a loaded keystore object of the appropriate keystore type.1685* First the keystore type is determined by probing the specified file.1686* Then a keystore object is instantiated and loaded using the data from1687* that file.1688* A {@code LoadStoreParameter} may be supplied which specifies how to1689* unlock the keystore data or perform an integrity check.1690*1691* <p>1692* This method traverses the list of registered security {@linkplain1693* Provider providers}, starting with the most preferred Provider.1694* For each {@link KeyStoreSpi} implementation supported by a1695* Provider, it invokes the {@link1696* KeyStoreSpi#engineProbe(InputStream) engineProbe} method to1697* determine if it supports the specified keystore.1698* A new KeyStore object is returned that encapsulates the KeyStoreSpi1699* implementation from the first Provider that supports the specified file.1700*1701* <p> Note that the list of registered providers may be retrieved via1702* the {@link Security#getProviders() Security.getProviders()} method.1703*1704* @param file the keystore file1705* @param param the {@code LoadStoreParameter} that specifies how to load1706* the keystore, which may be {@code null}1707*1708* @return a keystore object loaded with keystore data1709*1710* @throws KeyStoreException if no Provider supports a KeyStoreSpi1711* implementation for the specified keystore file.1712* @throws IOException if there is an I/O or format problem with the1713* keystore data. If the error is due to an incorrect1714* {@code ProtectionParameter} (e.g. wrong password)1715* the {@link Throwable#getCause cause} of the1716* {@code IOException} should be an1717* {@code UnrecoverableKeyException}.1718* @throws NoSuchAlgorithmException if the algorithm used to check the1719* integrity of the keystore cannot be found.1720* @throws CertificateException if any of the certificates in the1721* keystore could not be loaded.1722* @throws IllegalArgumentException if file does not exist or does not1723* refer to a normal file, or if param is not recognized.1724* @throws NullPointerException if file is {@code null}.1725* @throws SecurityException if a security manager exists and its1726* {@link java.lang.SecurityManager#checkRead} method denies1727* read access to the specified file.1728*1729* @see Provider1730*1731* @since 91732*/1733public static final KeyStore getInstance(File file,1734LoadStoreParameter param) throws KeyStoreException, IOException,1735NoSuchAlgorithmException, CertificateException {1736return getInstance(file, null, param, false);1737}17381739// Used by getInstance(File, char[]) & getInstance(File, LoadStoreParameter)1740private static final KeyStore getInstance(File file, char[] password,1741LoadStoreParameter param, boolean hasPassword)1742throws KeyStoreException, IOException, NoSuchAlgorithmException,1743CertificateException {17441745if (file == null) {1746throw new NullPointerException();1747}17481749if (file.isFile() == false) {1750throw new IllegalArgumentException(1751"File does not exist or it does not refer to a normal file: " +1752file);1753}17541755KeyStore keystore = null;17561757try (DataInputStream dataStream =1758new DataInputStream(1759new BufferedInputStream(1760new FileInputStream(file)))) {17611762dataStream.mark(Integer.MAX_VALUE);17631764// Detect the keystore type1765for (Provider p : Security.getProviders()) {1766for (Provider.Service s : p.getServices()) {1767if (s.getType().equals("KeyStore")) {1768try {1769KeyStoreSpi impl = (KeyStoreSpi) s.newInstance(null);1770if (impl.engineProbe(dataStream)) {1771if (kdebug != null) {1772kdebug.println(s.getAlgorithm()1773+ " keystore detected: " + file);1774}1775keystore = new KeyStore(impl, p, s.getAlgorithm());1776break;1777}1778} catch (NoSuchAlgorithmException e) {1779// ignore1780if (kdebug != null) {1781kdebug.println("not found - " + e);1782}1783} catch (IOException e) {1784// ignore1785if (kdebug != null) {1786kdebug.println("I/O error in " + file + " - " + e);1787}1788}1789dataStream.reset(); // prepare the stream for the next probe1790}1791}1792}17931794// Load the keystore data1795if (keystore != null) {1796dataStream.reset(); // prepare the stream for loading1797if (hasPassword) {1798keystore.load(dataStream, password);1799} else {1800keystore.keyStoreSpi.engineLoad(dataStream, param);1801keystore.initialized = true;1802}1803return keystore;1804}1805}18061807throw new KeyStoreException("Unrecognized keystore format. "1808+ "Please load it with a specified type");1809}18101811/**1812* A description of a to-be-instantiated KeyStore object.1813*1814* <p>An instance of this class encapsulates the information needed to1815* instantiate and initialize a KeyStore object. That process is1816* triggered when the {@linkplain #getKeyStore} method is called.1817*1818* <p>This makes it possible to decouple configuration from KeyStore1819* object creation and e.g. delay a password prompt until it is1820* needed.1821*1822* @see KeyStore1823* @see javax.net.ssl.KeyStoreBuilderParameters1824* @since 1.51825*/1826public abstract static class Builder {18271828// maximum times to try the callbackhandler if the password is wrong1829static final int MAX_CALLBACK_TRIES = 3;18301831/**1832* Construct a new Builder.1833*/1834protected Builder() {1835// empty1836}18371838/**1839* Returns the KeyStore described by this object.1840*1841* @return the {@code KeyStore} described by this object1842* @throws KeyStoreException if an error occurred during the1843* operation, for example if the KeyStore could not be1844* instantiated or loaded1845*/1846public abstract KeyStore getKeyStore() throws KeyStoreException;18471848/**1849* Returns the ProtectionParameters that should be used to obtain1850* the {@link KeyStore.Entry Entry} with the given alias.1851* The {@code getKeyStore} method must be invoked before this1852* method may be called.1853*1854* @return the ProtectionParameters that should be used to obtain1855* the {@link KeyStore.Entry Entry} with the given alias.1856* @param alias the alias of the KeyStore entry1857* @throws NullPointerException if alias is null1858* @throws KeyStoreException if an error occurred during the1859* operation1860* @throws IllegalStateException if the getKeyStore method has1861* not been invoked prior to calling this method1862*/1863public abstract ProtectionParameter getProtectionParameter(String alias)1864throws KeyStoreException;18651866/**1867* Returns a new Builder that encapsulates the given KeyStore.1868* The {@linkplain #getKeyStore} method of the returned object1869* will return {@code keyStore}, the {@linkplain1870* #getProtectionParameter getProtectionParameter()} method will1871* return {@code protectionParameters}.1872*1873* <p> This is useful if an existing KeyStore object needs to be1874* used with Builder-based APIs.1875*1876* @return a new Builder object1877* @param keyStore the KeyStore to be encapsulated1878* @param protectionParameter the ProtectionParameter used to1879* protect the KeyStore entries1880* @throws NullPointerException if keyStore or1881* protectionParameters is null1882* @throws IllegalArgumentException if the keyStore has not been1883* initialized1884*/1885public static Builder newInstance(final KeyStore keyStore,1886final ProtectionParameter protectionParameter) {1887if ((keyStore == null) || (protectionParameter == null)) {1888throw new NullPointerException();1889}1890if (keyStore.initialized == false) {1891throw new IllegalArgumentException("KeyStore not initialized");1892}1893return new Builder() {1894private volatile boolean getCalled;18951896public KeyStore getKeyStore() {1897getCalled = true;1898return keyStore;1899}19001901public ProtectionParameter getProtectionParameter(String alias)1902{1903if (alias == null) {1904throw new NullPointerException();1905}1906if (getCalled == false) {1907throw new IllegalStateException1908("getKeyStore() must be called first");1909}1910return protectionParameter;1911}1912};1913}19141915/**1916* Returns a new Builder object.1917*1918* <p>The first call to the {@link #getKeyStore} method on the returned1919* builder will create a KeyStore of type {@code type} and call1920* its {@link KeyStore#load load()} method.1921* The {@code inputStream} argument is constructed from1922* {@code file}.1923* If {@code protection} is a1924* {@code PasswordProtection}, the password is obtained by1925* calling the {@code getPassword} method.1926* Otherwise, if {@code protection} is a1927* {@code CallbackHandlerProtection}, the password is obtained1928* by invoking the CallbackHandler.1929*1930* <p>Subsequent calls to {@link #getKeyStore} return the same object1931* as the initial call. If the initial call failed with a1932* KeyStoreException, subsequent calls also throw a1933* KeyStoreException.1934*1935* <p>The KeyStore is instantiated from {@code provider} if1936* non-null. Otherwise, all installed providers are searched.1937*1938* <p>Calls to {@link #getProtectionParameter getProtectionParameter()}1939* will return a {@link KeyStore.PasswordProtection PasswordProtection}1940* object encapsulating the password that was used to invoke the1941* {@code load} method.1942*1943* <p><em>Note</em> that the {@link #getKeyStore} method is executed1944* within the {@link AccessControlContext} of the code invoking this1945* method.1946*1947* @return a new Builder object1948* @param type the type of KeyStore to be constructed1949* @param provider the provider from which the KeyStore is to1950* be instantiated (or null)1951* @param file the File that contains the KeyStore data1952* @param protection the ProtectionParameter securing the KeyStore data1953* @throws NullPointerException if type, file or protection is null1954* @throws IllegalArgumentException if protection is not an instance1955* of either PasswordProtection or CallbackHandlerProtection; or1956* if file does not exist or does not refer to a normal file1957*/1958public static Builder newInstance(String type, Provider provider,1959File file, ProtectionParameter protection) {1960if ((type == null) || (file == null) || (protection == null)) {1961throw new NullPointerException();1962}1963if (!(protection instanceof PasswordProtection) &&1964!(protection instanceof CallbackHandlerProtection)) {1965throw new IllegalArgumentException1966("Protection must be PasswordProtection or " +1967"CallbackHandlerProtection");1968}1969if (!file.isFile()) {1970throw new IllegalArgumentException1971("File does not exist or it does not refer " +1972"to a normal file: " + file);1973}1974@SuppressWarnings("removal")1975var acc = AccessController.getContext();1976return new FileBuilder(type, provider, file, protection, acc);1977}19781979/**1980* Returns a new Builder object.1981*1982* <p>The first call to the {@link #getKeyStore} method on the returned1983* builder will create a KeyStore using {@code file} to detect the1984* keystore type and then call its {@link KeyStore#load load()} method.1985* It uses the same algorithm to determine the keystore type as1986* described in {@link KeyStore#getInstance(File, LoadStoreParameter)}.1987* The {@code inputStream} argument is constructed from {@code file}.1988* If {@code protection} is a {@code PasswordProtection}, the password1989* is obtained by calling the {@code getPassword} method.1990* Otherwise, if {@code protection} is a1991* {@code CallbackHandlerProtection},1992* the password is obtained by invoking the CallbackHandler.1993*1994* <p>Subsequent calls to {@link #getKeyStore} return the same object1995* as the initial call. If the initial call failed with a1996* KeyStoreException, subsequent calls also throw a KeyStoreException.1997*1998* <p>Calls to {@link #getProtectionParameter getProtectionParameter()}1999* will return a {@link KeyStore.PasswordProtection PasswordProtection}2000* object encapsulating the password that was used to invoke the2001* {@code load} method.2002*2003* <p><em>Note</em> that the {@link #getKeyStore} method is executed2004* within the {@link AccessControlContext} of the code invoking this2005* method.2006*2007* @return a new Builder object2008* @param file the File that contains the KeyStore data2009* @param protection the ProtectionParameter securing the KeyStore data2010* @throws NullPointerException if file or protection is null2011* @throws IllegalArgumentException if protection is not an instance2012* of either PasswordProtection or CallbackHandlerProtection; or2013* if file does not exist or does not refer to a normal file2014*2015* @since 92016*/2017public static Builder newInstance(File file,2018ProtectionParameter protection) {20192020return newInstance("", null, file, protection);2021}20222023private static final class FileBuilder extends Builder {20242025private final String type;2026private final Provider provider;2027private final File file;2028private ProtectionParameter protection;2029private ProtectionParameter keyProtection;2030@SuppressWarnings("removal")2031private final AccessControlContext context;20322033private KeyStore keyStore;20342035private Throwable oldException;20362037FileBuilder(String type, Provider provider, File file,2038ProtectionParameter protection,2039@SuppressWarnings("removal") AccessControlContext context) {2040this.type = type;2041this.provider = provider;2042this.file = file;2043this.protection = protection;2044this.context = context;2045}20462047@SuppressWarnings("removal")2048public synchronized KeyStore getKeyStore() throws KeyStoreException2049{2050if (keyStore != null) {2051return keyStore;2052}2053if (oldException != null) {2054throw new KeyStoreException2055("Previous KeyStore instantiation failed",2056oldException);2057}2058PrivilegedExceptionAction<KeyStore> action =2059new PrivilegedExceptionAction<KeyStore>() {2060public KeyStore run() throws Exception {2061if (!(protection instanceof CallbackHandlerProtection)) {2062return run0();2063}2064// when using a CallbackHandler,2065// reprompt if the password is wrong2066int tries = 0;2067while (true) {2068tries++;2069try {2070return run0();2071} catch (IOException e) {2072if ((tries < MAX_CALLBACK_TRIES)2073&& (e.getCause() instanceof UnrecoverableKeyException)) {2074continue;2075}2076throw e;2077}2078}2079}2080public KeyStore run0() throws Exception {2081KeyStore ks;2082char[] password = null;20832084// Acquire keystore password2085if (protection instanceof PasswordProtection) {2086password =2087((PasswordProtection)protection).getPassword();2088keyProtection = protection;2089} else {2090CallbackHandler handler =2091((CallbackHandlerProtection)protection)2092.getCallbackHandler();2093PasswordCallback callback = new PasswordCallback2094("Password for keystore " + file.getName(),2095false);2096handler.handle(new Callback[] {callback});2097password = callback.getPassword();2098if (password == null) {2099throw new KeyStoreException("No password" +2100" provided");2101}2102callback.clearPassword();2103keyProtection = new PasswordProtection(password);2104}21052106if (type.isEmpty()) {2107// Instantiate keystore and load keystore data2108ks = KeyStore.getInstance(file, password);2109} else {2110// Instantiate keystore2111if (provider == null) {2112ks = KeyStore.getInstance(type);2113} else {2114ks = KeyStore.getInstance(type, provider);2115}2116// Load keystore data2117try (InputStream in = new FileInputStream(file)) {2118ks.load(in, password);2119}2120}2121return ks;2122}2123};2124try {2125keyStore = AccessController.doPrivileged(action, context);2126return keyStore;2127} catch (PrivilegedActionException e) {2128oldException = e.getCause();2129throw new KeyStoreException2130("KeyStore instantiation failed", oldException);2131}2132}21332134public synchronized ProtectionParameter2135getProtectionParameter(String alias) {2136if (alias == null) {2137throw new NullPointerException();2138}2139if (keyStore == null) {2140throw new IllegalStateException2141("getKeyStore() must be called first");2142}2143return keyProtection;2144}2145}21462147/**2148* Returns a new Builder object.2149*2150* <p>Each call to the {@link #getKeyStore} method on the returned2151* builder will return a new KeyStore object of type {@code type}.2152* Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()}2153* method is invoked using a2154* {@code LoadStoreParameter} that encapsulates2155* {@code protection}.2156*2157* <p>The KeyStore is instantiated from {@code provider} if2158* non-null. Otherwise, all installed providers are searched.2159*2160* <p>Calls to {@link #getProtectionParameter getProtectionParameter()}2161* will return {@code protection}.2162*2163* <p><em>Note</em> that the {@link #getKeyStore} method is executed2164* within the {@link AccessControlContext} of the code invoking this2165* method.2166*2167* @return a new Builder object2168* @param type the type of KeyStore to be constructed2169* @param provider the provider from which the KeyStore is to2170* be instantiated (or null)2171* @param protection the ProtectionParameter securing the Keystore2172* @throws NullPointerException if type or protection is null2173*/2174public static Builder newInstance(final String type,2175final Provider provider, final ProtectionParameter protection) {2176if ((type == null) || (protection == null)) {2177throw new NullPointerException();2178}2179@SuppressWarnings("removal")2180final AccessControlContext context = AccessController.getContext();2181return new Builder() {2182private volatile boolean getCalled;2183private IOException oldException;21842185private final PrivilegedExceptionAction<KeyStore> action2186= new PrivilegedExceptionAction<KeyStore>() {21872188public KeyStore run() throws Exception {2189KeyStore ks;2190if (provider == null) {2191ks = KeyStore.getInstance(type);2192} else {2193ks = KeyStore.getInstance(type, provider);2194}2195LoadStoreParameter param = new SimpleLoadStoreParameter(protection);2196if (!(protection instanceof CallbackHandlerProtection)) {2197ks.load(param);2198} else {2199// when using a CallbackHandler,2200// reprompt if the password is wrong2201int tries = 0;2202while (true) {2203tries++;2204try {2205ks.load(param);2206break;2207} catch (IOException e) {2208if (e.getCause() instanceof UnrecoverableKeyException) {2209if (tries < MAX_CALLBACK_TRIES) {2210continue;2211} else {2212oldException = e;2213}2214}2215throw e;2216}2217}2218}2219getCalled = true;2220return ks;2221}2222};22232224@SuppressWarnings("removal")2225public synchronized KeyStore getKeyStore()2226throws KeyStoreException {2227if (oldException != null) {2228throw new KeyStoreException2229("Previous KeyStore instantiation failed",2230oldException);2231}2232try {2233return AccessController.doPrivileged(action, context);2234} catch (PrivilegedActionException e) {2235Throwable cause = e.getCause();2236throw new KeyStoreException2237("KeyStore instantiation failed", cause);2238}2239}22402241public ProtectionParameter getProtectionParameter(String alias)2242{2243if (alias == null) {2244throw new NullPointerException();2245}2246if (getCalled == false) {2247throw new IllegalStateException2248("getKeyStore() must be called first");2249}2250return protection;2251}2252};2253}22542255}22562257static class SimpleLoadStoreParameter implements LoadStoreParameter {22582259private final ProtectionParameter protection;22602261SimpleLoadStoreParameter(ProtectionParameter protection) {2262this.protection = protection;2263}22642265public ProtectionParameter getProtectionParameter() {2266return protection;2267}2268}2269}227022712272