2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package java.security;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.security.cert.Certificate;
24 import java.security.cert.CertificateException;
25 import java.util.Date;
26 import java.util.Enumeration;
27 import javax.crypto.SecretKey;
28 import javax.security.auth.callback.CallbackHandler;
29 import javax.security.auth.callback.PasswordCallback;
32 * {@code KeyStoreSpi} is the Service Provider Interface (SPI) definition for
37 public abstract class KeyStoreSpi {
40 * Returns the key with the given alias, using the password to recover the
44 * the alias for the entry.
46 * the password used to recover the key.
47 * @return the key with the specified alias, or {@code null} if the
48 * specified alias is not bound to an entry.
49 * @throws NoSuchAlgorithmException
50 * if the algorithm for recovering the key is not available.
51 * @throws UnrecoverableKeyException
52 * if the key can not be recovered.
54 public abstract Key engineGetKey(String alias, char[] password)
55 throws NoSuchAlgorithmException, UnrecoverableKeyException;
58 * Returns the certificate chain for the entry with the given alias.
61 * the alias for the entry
62 * @return the certificate chain for the entry with the given alias, or
63 * {@code null} if the specified alias is not bound to an entry.
65 public abstract Certificate[] engineGetCertificateChain(String alias);
68 * Returns the trusted certificate for the entry with the given alias.
71 * the alias for the entry.
72 * @return the trusted certificate for the entry with the given alias, or
73 * {@code null} if the specified alias is not bound to an entry.
75 public abstract Certificate engineGetCertificate(String alias);
78 * Returns the creation date of the entry with the given alias.
81 * the alias for the entry.
82 * @return the creation date, or {@code null} if the specified alias is not
85 public abstract Date engineGetCreationDate(String alias);
88 * Associates the given alias with the key, password and certificate chain.
90 * If the specified alias already exists, it will be reassigned.
93 * the alias for the key.
99 * the certificate chain.
100 * @throws KeyStoreException
101 * if the specified key can not be protected, or if this
102 * operation fails for another reason.
103 * @throws IllegalArgumentException
104 * if {@code key} is a {@code PrivateKey} and {@code chain} does
105 * not contain any certificates.
107 public abstract void engineSetKeyEntry(String alias, Key key,
108 char[] password, Certificate[] chain) throws KeyStoreException;
111 * Associates the given alias with a key and a certificate chain.
113 * If the specified alias already exists, it will be reassigned.
116 * the alias for the key.
118 * the key in an encoded format.
120 * the certificate chain.
121 * @throws KeyStoreException
122 * if this operation fails.
123 * @throws IllegalArgumentException
124 * if {@code key} is a {@code PrivateKey} and {@code chain}
127 public abstract void engineSetKeyEntry(String alias, byte[] key,
128 Certificate[] chain) throws KeyStoreException;
131 * Associates the given alias with a certificate.
133 * If the specified alias already exists, it will be reassigned.
136 * the alias for the certificate.
139 * @throws KeyStoreException
140 * if an existing alias is not associated to an entry containing
141 * a trusted certificate, or this method fails for any other
144 public abstract void engineSetCertificateEntry(String alias,
145 Certificate cert) throws KeyStoreException;
148 * Deletes the entry identified with the given alias from this {@code
152 * the alias for the entry.
153 * @throws KeyStoreException
154 * if the entry can not be deleted.
156 public abstract void engineDeleteEntry(String alias)
157 throws KeyStoreException;
160 * Returns an {@code Enumeration} over all alias names stored in this
161 * {@code KeyStoreSpi}.
163 * @return an {@code Enumeration} over all alias names stored in this
164 * {@code KeyStoreSpi}.
166 public abstract Enumeration<String> engineAliases();
169 * Indicates whether the given alias is present in this {@code KeyStoreSpi}.
172 * the alias of an entry.
173 * @return {@code true} if the alias exists, {@code false} otherwise.
175 public abstract boolean engineContainsAlias(String alias);
178 * Returns the number of entries stored in this {@code KeyStoreSpi}.
180 * @return the number of entries stored in this {@code KeyStoreSpi}.
182 public abstract int engineSize();
185 * Indicates whether the specified alias is associated with either a
186 * {@link KeyStore.PrivateKeyEntry} or a {@link KeyStore.SecretKeyEntry}.
189 * the alias of an entry.
190 * @return {@code true} if the given alias is associated with a key entry.
192 public abstract boolean engineIsKeyEntry(String alias);
195 * Indicates whether the specified alias is associated with a
196 * {@link KeyStore.TrustedCertificateEntry}.
199 * the alias of an entry.
200 * @return {@code true} if the given alias is associated with a certificate
203 public abstract boolean engineIsCertificateEntry(String alias);
206 * Returns the alias associated with the first entry whose certificate
207 * matches the specified certificate.
210 * the certificate to find the associated entry's alias for.
211 * @return the alias or {@code null} if no entry with the specified
212 * certificate can be found.
214 public abstract String engineGetCertificateAlias(Certificate cert);
217 * Writes this {@code KeyStoreSpi} to the specified {@code OutputStream}.
218 * The data written to the {@code OutputStream} is protected by the
219 * specified password.
222 * the {@code OutputStream} to write the store's data to.
224 * the password to protect the data.
225 * @throws IOException
226 * if a problem occurred while writing to the stream.
227 * @throws NoSuchAlgorithmException
228 * if the required algorithm is not available.
229 * @throws CertificateException
230 * if the an exception occurred while storing the certificates
231 * of this code {@code KeyStoreSpi}.
233 public abstract void engineStore(OutputStream stream, char[] password)
234 throws IOException, NoSuchAlgorithmException, CertificateException;
237 * Stores this {@code KeyStoreSpi} using the specified {@code
238 * LoadStoreParameter}.
241 * the {@code LoadStoreParameter} that specifies how to store
242 * this {@code KeyStoreSpi}, maybe {@code null}.
243 * @throws IOException
244 * if a problem occurred while writing to the stream.
245 * @throws NoSuchAlgorithmException
246 * if the required algorithm is not available.
247 * @throws CertificateException
248 * if the an exception occurred while storing the certificates
249 * of this code {@code KeyStoreSpi}.
250 * @throws IllegalArgumentException
251 * if the given {@link KeyStore.LoadStoreParameter} is not
254 public void engineStore(KeyStore.LoadStoreParameter param)
255 throws IOException, NoSuchAlgorithmException, CertificateException {
256 throw new UnsupportedOperationException();
260 * Loads this {@code KeyStoreSpi} from the given {@code InputStream}.
261 * Utilizes the given password to verify the stored data.
264 * the {@code InputStream} to load this {@code KeyStoreSpi}'s
267 * the password to verify the stored data, maybe {@code null}.
268 * @throws IOException
269 * if a problem occurred while reading from the stream.
270 * @throws NoSuchAlgorithmException
271 * if the required algorithm is not available.
272 * @throws CertificateException
273 * if the an exception occurred while loading the certificates
274 * of this code {@code KeyStoreSpi}.
276 public abstract void engineLoad(InputStream stream, char[] password)
277 throws IOException, NoSuchAlgorithmException, CertificateException;
280 * Loads this {@code KeyStoreSpi} using the specified {@code
281 * LoadStoreParameter}.
284 * the {@code LoadStoreParameter} that specifies how to load this
285 * {@code KeyStoreSpi}, maybe {@code null}.
286 * @throws IOException
287 * if a problem occurred while reading from the stream.
288 * @throws NoSuchAlgorithmException
289 * if the required algorithm is not available.
290 * @throws CertificateException
291 * if the an exception occurred while loading the certificates
292 * of this code {@code KeyStoreSpi}.
293 * @throws IllegalArgumentException
294 * if the given {@link KeyStore.LoadStoreParameter} is not
297 public void engineLoad(KeyStore.LoadStoreParameter param)
298 throws IOException, NoSuchAlgorithmException, CertificateException {
300 engineLoad(null, null);
304 KeyStore.ProtectionParameter pp = param.getProtectionParameter();
305 if (pp instanceof KeyStore.PasswordProtection) {
307 pwd = ((KeyStore.PasswordProtection) pp).getPassword();
308 engineLoad(null, pwd);
310 } catch (IllegalStateException e) {
311 throw new IllegalArgumentException(e);
314 if (pp instanceof KeyStore.CallbackHandlerProtection) {
316 pwd = getPasswordFromCallBack(pp);
317 engineLoad(null, pwd);
319 } catch (UnrecoverableEntryException e) {
320 throw new IllegalArgumentException(e);
323 throw new UnsupportedOperationException("protectionParameter is neither PasswordProtection "
324 + "nor CallbackHandlerProtection instance");
328 * Returns the {@code Entry} with the given alias, using the specified
329 * {@code ProtectionParameter}.
332 * the alias of the requested entry.
334 * the {@code ProtectionParameter}, used to protect the requested
335 * entry, maybe {@code null}.
336 * @return he {@code Entry} with the given alias, using the specified
337 * {@code ProtectionParameter}.
338 * @throws NoSuchAlgorithmException
339 * if the required algorithm is not available.
340 * @throws UnrecoverableEntryException
341 * if the entry can not be recovered.
342 * @throws KeyStoreException
343 * if this operation fails
345 public KeyStore.Entry engineGetEntry(String alias,
346 KeyStore.ProtectionParameter protParam) throws KeyStoreException,
347 NoSuchAlgorithmException, UnrecoverableEntryException {
348 if (!engineContainsAlias(alias)) {
351 if (engineIsCertificateEntry(alias)) {
352 return new KeyStore.TrustedCertificateEntry(
353 engineGetCertificate(alias));
356 if (protParam != null) {
357 if (protParam instanceof KeyStore.PasswordProtection) {
359 passW = ((KeyStore.PasswordProtection) protParam)
361 } catch (IllegalStateException ee) {
362 throw new KeyStoreException("Password was destroyed", ee);
364 } else if (protParam instanceof KeyStore.CallbackHandlerProtection) {
365 passW = getPasswordFromCallBack(protParam);
367 throw new UnrecoverableEntryException("ProtectionParameter object is not "
368 + "PasswordProtection: " + protParam);
371 if (engineIsKeyEntry(alias)) {
372 Key key = engineGetKey(alias, passW);
373 if (key instanceof PrivateKey) {
374 return new KeyStore.PrivateKeyEntry((PrivateKey) key,
375 engineGetCertificateChain(alias));
377 if (key instanceof SecretKey) {
378 return new KeyStore.SecretKeyEntry((SecretKey) key);
381 throw new NoSuchAlgorithmException("Unknown KeyStore.Entry object");
385 * Stores the given {@code Entry} in this {@code KeyStoreSpi} and associates
386 * the entry with the given {@code alias}. The entry is protected by the
387 * specified {@code ProtectionParameter}.
389 * If the specified alias already exists, it will be reassigned.
392 * the alias for the entry.
394 * the entry to store.
396 * the {@code ProtectionParameter} to protect the entry.
397 * @throws KeyStoreException
398 * if this operation fails.
400 public void engineSetEntry(String alias, KeyStore.Entry entry,
401 KeyStore.ProtectionParameter protParam) throws KeyStoreException {
403 throw new KeyStoreException("entry == null");
406 if (engineContainsAlias(alias)) {
407 engineDeleteEntry(alias);
410 if (entry instanceof KeyStore.TrustedCertificateEntry) {
411 KeyStore.TrustedCertificateEntry trE = (KeyStore.TrustedCertificateEntry) entry;
412 engineSetCertificateEntry(alias, trE.getTrustedCertificate());
417 if (protParam instanceof KeyStore.PasswordProtection) {
419 passW = ((KeyStore.PasswordProtection) protParam).getPassword();
420 } catch (IllegalStateException ee) {
421 throw new KeyStoreException("Password was destroyed", ee);
424 if (protParam instanceof KeyStore.CallbackHandlerProtection) {
426 passW = getPasswordFromCallBack(protParam);
427 } catch (Exception e) {
428 throw new KeyStoreException(e);
431 throw new KeyStoreException("protParam should be PasswordProtection or "
432 + "CallbackHandlerProtection");
436 if (entry instanceof KeyStore.PrivateKeyEntry) {
437 KeyStore.PrivateKeyEntry prE = (KeyStore.PrivateKeyEntry) entry;
438 engineSetKeyEntry(alias, prE.getPrivateKey(), passW, prE
439 .getCertificateChain());
443 if (entry instanceof KeyStore.SecretKeyEntry) {
444 KeyStore.SecretKeyEntry skE = (KeyStore.SecretKeyEntry) entry;
445 engineSetKeyEntry(alias, skE.getSecretKey(), passW, null);
446 // engineSetKeyEntry(alias, skE.getSecretKey().getEncoded(), null);
450 throw new KeyStoreException("Entry object is neither PrivateKeyObject nor SecretKeyEntry "
451 + "nor TrustedCertificateEntry: " + entry);
455 * Indicates whether the entry for the given alias is assignable to the
456 * provided {@code Class}.
459 * the alias for the entry.
461 * the type of the entry.
462 * @return {@code true} if the {@code Entry} for the alias is assignable to
463 * the specified {@code entryClass}.
465 public boolean engineEntryInstanceOf(String alias,
466 Class<? extends KeyStore.Entry> entryClass) {
467 if (!engineContainsAlias(alias)) {
472 if (engineIsCertificateEntry(alias)) {
474 .isAssignableFrom(Class
475 .forName("java.security.KeyStore$TrustedCertificateEntry"));
478 if (engineIsKeyEntry(alias)) {
479 if (entryClass.isAssignableFrom(Class
480 .forName("java.security.KeyStore$PrivateKeyEntry"))) {
481 return engineGetCertificate(alias) != null;
484 if (entryClass.isAssignableFrom(Class
485 .forName("java.security.KeyStore$SecretKeyEntry"))) {
486 return engineGetCertificate(alias) == null;
489 } catch (ClassNotFoundException ignore) {}
495 * This method returns password which is encapsulated in
496 * CallbackHandlerProtection object If there is no implementation of
497 * CallbackHandler then this method returns null
499 static char[] getPasswordFromCallBack(KeyStore.ProtectionParameter protParam)
500 throws UnrecoverableEntryException {
502 if (protParam == null) {
506 if (!(protParam instanceof KeyStore.CallbackHandlerProtection)) {
507 throw new UnrecoverableEntryException("Incorrect ProtectionParameter");
510 String clName = Security.getProperty("auth.login.defaultCallbackHandler");
511 if (clName == null) {
512 throw new UnrecoverableEntryException("Default CallbackHandler was not defined");
517 Class<?> cl = Class.forName(clName);
518 CallbackHandler cbHand = (CallbackHandler) cl.newInstance();
519 PasswordCallback[] pwCb = { new PasswordCallback("password: ", true) };
521 return pwCb[0].getPassword();
522 } catch (Exception e) {
523 throw new UnrecoverableEntryException(e.toString());