Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/java/security/KeyStore.java
41152 views
1
/*
2
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.security;
27
28
import java.io.*;
29
import java.security.cert.Certificate;
30
import java.security.cert.X509Certificate;
31
import java.security.cert.CertificateException;
32
import java.security.spec.AlgorithmParameterSpec;
33
import java.util.*;
34
import javax.crypto.SecretKey;
35
36
import javax.security.auth.DestroyFailedException;
37
import javax.security.auth.callback.*;
38
39
import sun.security.util.Debug;
40
41
/**
42
* This class represents a storage facility for cryptographic
43
* keys and certificates.
44
*
45
* <p> A {@code KeyStore} manages different types of entries.
46
* Each type of entry implements the {@code KeyStore.Entry} interface.
47
* Three basic {@code KeyStore.Entry} implementations are provided:
48
*
49
* <ul>
50
* <li><b>KeyStore.PrivateKeyEntry</b>
51
* <p> This type of entry holds a cryptographic {@code PrivateKey},
52
* which is optionally stored in a protected format to prevent
53
* unauthorized access. It is also accompanied by a certificate chain
54
* for the corresponding public key.
55
*
56
* <p> Private keys and certificate chains are used by a given entity for
57
* self-authentication. Applications for this authentication include software
58
* distribution organizations which sign JAR files as part of releasing
59
* and/or licensing software.
60
*
61
* <li><b>KeyStore.SecretKeyEntry</b>
62
* <p> This type of entry holds a cryptographic {@code SecretKey},
63
* which is optionally stored in a protected format to prevent
64
* unauthorized access.
65
*
66
* <li><b>KeyStore.TrustedCertificateEntry</b>
67
* <p> This type of entry contains a single public key {@code Certificate}
68
* belonging to another party. It is called a <i>trusted certificate</i>
69
* because the keystore owner trusts that the public key in the certificate
70
* indeed belongs to the identity identified by the <i>subject</i> (owner)
71
* of the certificate.
72
*
73
* <p>This type of entry can be used to authenticate other parties.
74
* </ul>
75
*
76
* <p> Each entry in a keystore is identified by an "alias" string. In the
77
* case of private keys and their associated certificate chains, these strings
78
* distinguish among the different ways in which the entity may authenticate
79
* itself. For example, the entity may authenticate itself using different
80
* certificate authorities, or using different public key algorithms.
81
*
82
* <p> Whether aliases are case sensitive is implementation dependent. In order
83
* to avoid problems, it is recommended not to use aliases in a KeyStore that
84
* only differ in case.
85
*
86
* <p> Whether keystores are persistent, and the mechanisms used by the
87
* keystore if it is persistent, are not specified here. This allows
88
* use of a variety of techniques for protecting sensitive (e.g., private or
89
* secret) keys. Smart cards or other integrated cryptographic engines
90
* (SafeKeyper) are one option, and simpler mechanisms such as files may also
91
* be used (in a variety of formats).
92
*
93
* <p> Typical ways to request a KeyStore object include
94
* specifying an existing keystore file,
95
* relying on the default type and providing a specific keystore type.
96
*
97
* <ul>
98
* <li>To specify an existing keystore file:
99
* <pre>
100
* // get keystore password
101
* char[] password = getPassword();
102
*
103
* // probe the keystore file and load the keystore entries
104
* KeyStore ks = KeyStore.getInstance(new File("keyStoreName"), password);
105
*</pre>
106
* The system will probe the specified file to determine its keystore type
107
* and return a keystore implementation with its entries already loaded.
108
* When this approach is used there is no need to call the keystore's
109
* {@link #load(java.io.InputStream, char[]) load} method.
110
*
111
* <li>To rely on the default type:
112
* <pre>
113
* KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
114
* </pre>
115
* The system will return a keystore implementation for the default type.
116
*
117
* <li>To provide a specific keystore type:
118
* <pre>
119
* KeyStore ks = KeyStore.getInstance("JKS");
120
* </pre>
121
* The system will return the most preferred implementation of the
122
* specified keystore type available in the environment.
123
* </ul>
124
*
125
* <p> Before a keystore can be accessed, it must be
126
* {@link #load(java.io.InputStream, char[]) loaded}
127
* (unless it was already loaded during instantiation).
128
* <pre>
129
* KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
130
*
131
* // get user password and file input stream
132
* char[] password = getPassword();
133
*
134
* try (FileInputStream fis = new FileInputStream("keyStoreName")) {
135
* ks.load(fis, password);
136
* }
137
* </pre>
138
*
139
* To create an empty keystore using the above {@code load} method,
140
* pass {@code null} as the {@code InputStream} argument.
141
*
142
* <p> Once the keystore has been loaded, it is possible
143
* to read existing entries from the keystore, or to write new entries
144
* into the keystore:
145
* <pre>
146
* KeyStore.ProtectionParameter protParam =
147
* new KeyStore.PasswordProtection(password);
148
*
149
* // get my private key
150
* KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
151
* ks.getEntry("privateKeyAlias", protParam);
152
* PrivateKey myPrivateKey = pkEntry.getPrivateKey();
153
*
154
* // save my secret key
155
* javax.crypto.SecretKey mySecretKey;
156
* KeyStore.SecretKeyEntry skEntry =
157
* new KeyStore.SecretKeyEntry(mySecretKey);
158
* ks.setEntry("secretKeyAlias", skEntry, protParam);
159
*
160
* // store away the keystore
161
* try (FileOutputStream fos = new FileOutputStream("newKeyStoreName")) {
162
* ks.store(fos, password);
163
* }
164
* </pre>
165
*
166
* Note that although the same password may be used to
167
* load the keystore, to protect the private key entry,
168
* to protect the secret key entry, and to store the keystore
169
* (as is shown in the sample code above),
170
* different passwords or other protection parameters
171
* may also be used.
172
*
173
* <p> Every implementation of the Java platform is required to support
174
* the following standard {@code KeyStore} type:
175
* <ul>
176
* <li>{@code PKCS12}</li>
177
* </ul>
178
* This type is described in the <a href=
179
* "{@docRoot}/../specs/security/standard-names.html#keystore-types">
180
* KeyStore section</a> of the
181
* Java Security Standard Algorithm Names Specification.
182
* Consult the release documentation for your implementation to see if any
183
* other types are supported.
184
*
185
* @author Jan Luehe
186
*
187
* @see java.security.PrivateKey
188
* @see javax.crypto.SecretKey
189
* @see java.security.cert.Certificate
190
*
191
* @since 1.2
192
*/
193
194
public class KeyStore {
195
196
private static final Debug kdebug = Debug.getInstance("keystore");
197
private static final Debug pdebug =
198
Debug.getInstance("provider", "Provider");
199
private static final boolean skipDebug =
200
Debug.isOn("engine=") && !Debug.isOn("keystore");
201
202
/*
203
* Constant to lookup in the Security properties file to determine
204
* the default keystore type.
205
* In the Security properties file, the default keystore type is given as:
206
* <pre>
207
* keystore.type=jks
208
* </pre>
209
*/
210
private static final String KEYSTORE_TYPE = "keystore.type";
211
212
// The keystore type
213
private String type;
214
215
// The provider
216
private Provider provider;
217
218
// The provider implementation
219
private KeyStoreSpi keyStoreSpi;
220
221
// Has this keystore been initialized (loaded)?
222
private boolean initialized;
223
224
/**
225
* A marker interface for {@code KeyStore}
226
* {@link #load(KeyStore.LoadStoreParameter) load}
227
* and
228
* {@link #store(KeyStore.LoadStoreParameter) store}
229
* parameters.
230
*
231
* @since 1.5
232
*/
233
public static interface LoadStoreParameter {
234
/**
235
* Gets the parameter used to protect keystore data.
236
*
237
* @return the parameter used to protect keystore data, or null
238
*/
239
public ProtectionParameter getProtectionParameter();
240
}
241
242
/**
243
* A marker interface for keystore protection parameters.
244
*
245
* <p> The information stored in a {@code ProtectionParameter}
246
* object protects the contents of a keystore.
247
* For example, protection parameters may be used to check
248
* the integrity of keystore data, or to protect the
249
* confidentiality of sensitive keystore data
250
* (such as a {@code PrivateKey}).
251
*
252
* @since 1.5
253
*/
254
public static interface ProtectionParameter { }
255
256
/**
257
* A password-based implementation of {@code ProtectionParameter}.
258
*
259
* @since 1.5
260
*/
261
public static class PasswordProtection implements
262
ProtectionParameter, javax.security.auth.Destroyable {
263
264
private final char[] password;
265
private final String protectionAlgorithm;
266
private final AlgorithmParameterSpec protectionParameters;
267
private volatile boolean destroyed;
268
269
/**
270
* Creates a password parameter.
271
*
272
* <p> The specified {@code password} is cloned before it is stored
273
* in the new {@code PasswordProtection} object.
274
*
275
* @param password the password, which may be {@code null}
276
*/
277
public PasswordProtection(char[] password) {
278
this.password = (password == null) ? null : password.clone();
279
this.protectionAlgorithm = null;
280
this.protectionParameters = null;
281
}
282
283
/**
284
* Creates a password parameter and specifies the protection algorithm
285
* and associated parameters to use when encrypting a keystore entry.
286
* <p>
287
* The specified {@code password} is cloned before it is stored in the
288
* new {@code PasswordProtection} object.
289
*
290
* @param password the password, which may be {@code null}
291
* @param protectionAlgorithm the encryption algorithm name, for
292
* example, {@code PBEWithHmacSHA256AndAES_256}.
293
* See the Cipher section in the <a href=
294
* "{@docRoot}/../specs/security/standard-names.html#cipher-algorithm-names">
295
* Java Security Standard Algorithm Names Specification</a>
296
* for information about standard encryption algorithm names.
297
* @param protectionParameters the encryption algorithm parameter
298
* specification, which may be {@code null}
299
* @throws NullPointerException if {@code protectionAlgorithm} is
300
* {@code null}
301
*
302
* @since 1.8
303
*/
304
public PasswordProtection(char[] password, String protectionAlgorithm,
305
AlgorithmParameterSpec protectionParameters) {
306
if (protectionAlgorithm == null) {
307
throw new NullPointerException("invalid null input");
308
}
309
this.password = (password == null) ? null : password.clone();
310
this.protectionAlgorithm = protectionAlgorithm;
311
this.protectionParameters = protectionParameters;
312
}
313
314
/**
315
* Gets the name of the protection algorithm.
316
* If none was set then the keystore provider will use its default
317
* protection algorithm.
318
*
319
* @return the algorithm name, or {@code null} if none was set
320
*
321
* @since 1.8
322
*/
323
public String getProtectionAlgorithm() {
324
return protectionAlgorithm;
325
}
326
327
/**
328
* Gets the parameters supplied for the protection algorithm.
329
*
330
* @return the algorithm parameter specification, or {@code null},
331
* if none was set
332
*
333
* @since 1.8
334
*/
335
public AlgorithmParameterSpec getProtectionParameters() {
336
return protectionParameters;
337
}
338
339
/**
340
* Gets the password.
341
*
342
* <p>Note that this method returns a reference to the password.
343
* If a clone of the array is created it is the caller's
344
* responsibility to zero out the password information
345
* after it is no longer needed.
346
*
347
* @see #destroy()
348
* @return the password, which may be {@code null}
349
* @throws IllegalStateException if the password has
350
* been cleared (destroyed)
351
*/
352
public synchronized char[] getPassword() {
353
if (destroyed) {
354
throw new IllegalStateException("password has been cleared");
355
}
356
return password;
357
}
358
359
/**
360
* Clears the password.
361
*
362
* @throws DestroyFailedException if this method was unable
363
* to clear the password
364
*/
365
public synchronized void destroy() throws DestroyFailedException {
366
destroyed = true;
367
if (password != null) {
368
Arrays.fill(password, ' ');
369
}
370
}
371
372
/**
373
* Determines if password has been cleared.
374
*
375
* @return true if the password has been cleared, false otherwise
376
*/
377
public synchronized boolean isDestroyed() {
378
return destroyed;
379
}
380
}
381
382
/**
383
* A ProtectionParameter encapsulating a CallbackHandler.
384
*
385
* @since 1.5
386
*/
387
public static class CallbackHandlerProtection
388
implements ProtectionParameter {
389
390
private final CallbackHandler handler;
391
392
/**
393
* Constructs a new CallbackHandlerProtection from a
394
* CallbackHandler.
395
*
396
* @param handler the CallbackHandler
397
* @throws NullPointerException if handler is null
398
*/
399
public CallbackHandlerProtection(CallbackHandler handler) {
400
if (handler == null) {
401
throw new NullPointerException("handler must not be null");
402
}
403
this.handler = handler;
404
}
405
406
/**
407
* Returns the CallbackHandler.
408
*
409
* @return the CallbackHandler.
410
*/
411
public CallbackHandler getCallbackHandler() {
412
return handler;
413
}
414
415
}
416
417
/**
418
* A marker interface for {@code KeyStore} entry types.
419
*
420
* @since 1.5
421
*/
422
public static interface Entry {
423
424
/**
425
* Retrieves the attributes associated with an entry.
426
*
427
* @implSpec
428
* The default implementation returns an empty {@code Set}.
429
*
430
* @return an unmodifiable {@code Set} of attributes, possibly empty
431
*
432
* @since 1.8
433
*/
434
public default Set<Attribute> getAttributes() {
435
return Collections.<Attribute>emptySet();
436
}
437
438
/**
439
* An attribute associated with a keystore entry.
440
* It comprises a name and one or more values.
441
*
442
* @since 1.8
443
*/
444
public interface Attribute {
445
/**
446
* Returns the attribute's name.
447
*
448
* @return the attribute name
449
*/
450
public String getName();
451
452
/**
453
* Returns the attribute's value.
454
* Multi-valued attributes encode their values as a single string.
455
*
456
* @return the attribute value
457
*/
458
public String getValue();
459
}
460
}
461
462
/**
463
* A {@code KeyStore} entry that holds a {@code PrivateKey}
464
* and corresponding certificate chain.
465
*
466
* @since 1.5
467
*/
468
public static final class PrivateKeyEntry implements Entry {
469
470
private final PrivateKey privKey;
471
private final Certificate[] chain;
472
private final Set<Attribute> attributes;
473
474
/**
475
* Constructs a {@code PrivateKeyEntry} with a
476
* {@code PrivateKey} and corresponding certificate chain.
477
*
478
* <p> The specified {@code chain} is cloned before it is stored
479
* in the new {@code PrivateKeyEntry} object.
480
*
481
* @param privateKey the {@code PrivateKey}
482
* @param chain an array of {@code Certificate}s
483
* representing the certificate chain.
484
* The chain must be ordered and contain a
485
* {@code Certificate} at index 0
486
* corresponding to the private key.
487
*
488
* @throws NullPointerException if
489
* {@code privateKey} or {@code chain}
490
* is {@code null}
491
* @throws IllegalArgumentException if the specified chain has a
492
* length of 0, if the specified chain does not contain
493
* {@code Certificate}s of the same type,
494
* or if the {@code PrivateKey} algorithm
495
* does not match the algorithm of the {@code PublicKey}
496
* in the end entity {@code Certificate} (at index 0)
497
*/
498
public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain) {
499
this(privateKey, chain, Collections.<Attribute>emptySet());
500
}
501
502
/**
503
* Constructs a {@code PrivateKeyEntry} with a {@code PrivateKey} and
504
* corresponding certificate chain and associated entry attributes.
505
*
506
* <p> The specified {@code chain} and {@code attributes} are cloned
507
* before they are stored in the new {@code PrivateKeyEntry} object.
508
*
509
* @param privateKey the {@code PrivateKey}
510
* @param chain an array of {@code Certificate}s
511
* representing the certificate chain.
512
* The chain must be ordered and contain a
513
* {@code Certificate} at index 0
514
* corresponding to the private key.
515
* @param attributes the attributes
516
*
517
* @throws NullPointerException if {@code privateKey}, {@code chain}
518
* or {@code attributes} is {@code null}
519
* @throws IllegalArgumentException if the specified chain has a
520
* length of 0, if the specified chain does not contain
521
* {@code Certificate}s of the same type,
522
* or if the {@code PrivateKey} algorithm
523
* does not match the algorithm of the {@code PublicKey}
524
* in the end entity {@code Certificate} (at index 0)
525
*
526
* @since 1.8
527
*/
528
public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain,
529
Set<Attribute> attributes) {
530
531
if (privateKey == null || chain == null || attributes == null) {
532
throw new NullPointerException("invalid null input");
533
}
534
if (chain.length == 0) {
535
throw new IllegalArgumentException
536
("invalid zero-length input chain");
537
}
538
539
Certificate[] clonedChain = chain.clone();
540
String certType = clonedChain[0].getType();
541
for (int i = 1; i < clonedChain.length; i++) {
542
if (!certType.equals(clonedChain[i].getType())) {
543
throw new IllegalArgumentException
544
("chain does not contain certificates " +
545
"of the same type");
546
}
547
}
548
if (!privateKey.getAlgorithm().equals
549
(clonedChain[0].getPublicKey().getAlgorithm())) {
550
throw new IllegalArgumentException
551
("private key algorithm does not match " +
552
"algorithm of public key in end entity " +
553
"certificate (at index 0)");
554
}
555
this.privKey = privateKey;
556
557
if (clonedChain[0] instanceof X509Certificate &&
558
!(clonedChain instanceof X509Certificate[])) {
559
560
this.chain = new X509Certificate[clonedChain.length];
561
System.arraycopy(clonedChain, 0,
562
this.chain, 0, clonedChain.length);
563
} else {
564
this.chain = clonedChain;
565
}
566
567
this.attributes =
568
Collections.unmodifiableSet(new HashSet<>(attributes));
569
}
570
571
/**
572
* Gets the {@code PrivateKey} from this entry.
573
*
574
* @return the {@code PrivateKey} from this entry
575
*/
576
public PrivateKey getPrivateKey() {
577
return privKey;
578
}
579
580
/**
581
* Gets the {@code Certificate} chain from this entry.
582
*
583
* <p> The stored chain is cloned before being returned.
584
*
585
* @return an array of {@code Certificate}s corresponding
586
* to the certificate chain for the public key.
587
* If the certificates are of type X.509,
588
* the runtime type of the returned array is
589
* {@code X509Certificate[]}.
590
*/
591
public Certificate[] getCertificateChain() {
592
return chain.clone();
593
}
594
595
/**
596
* Gets the end entity {@code Certificate}
597
* from the certificate chain in this entry.
598
*
599
* @return the end entity {@code Certificate} (at index 0)
600
* from the certificate chain in this entry.
601
* If the certificate is of type X.509,
602
* the runtime type of the returned certificate is
603
* {@code X509Certificate}.
604
*/
605
public Certificate getCertificate() {
606
return chain[0];
607
}
608
609
/**
610
* Retrieves the attributes associated with an entry.
611
*
612
* @return an unmodifiable {@code Set} of attributes, possibly empty
613
*
614
* @since 1.8
615
*/
616
@Override
617
public Set<Attribute> getAttributes() {
618
return attributes;
619
}
620
621
/**
622
* Returns a string representation of this PrivateKeyEntry.
623
* @return a string representation of this PrivateKeyEntry.
624
*/
625
public String toString() {
626
StringBuilder sb = new StringBuilder();
627
sb.append("Private key entry and certificate chain with "
628
+ chain.length + " elements:\r\n");
629
for (Certificate cert : chain) {
630
sb.append(cert);
631
sb.append("\r\n");
632
}
633
return sb.toString();
634
}
635
636
}
637
638
/**
639
* A {@code KeyStore} entry that holds a {@code SecretKey}.
640
*
641
* @since 1.5
642
*/
643
public static final class SecretKeyEntry implements Entry {
644
645
private final SecretKey sKey;
646
private final Set<Attribute> attributes;
647
648
/**
649
* Constructs a {@code SecretKeyEntry} with a
650
* {@code SecretKey}.
651
*
652
* @param secretKey the {@code SecretKey}
653
*
654
* @throws NullPointerException if {@code secretKey}
655
* is {@code null}
656
*/
657
public SecretKeyEntry(SecretKey secretKey) {
658
if (secretKey == null) {
659
throw new NullPointerException("invalid null input");
660
}
661
this.sKey = secretKey;
662
this.attributes = Collections.<Attribute>emptySet();
663
}
664
665
/**
666
* Constructs a {@code SecretKeyEntry} with a {@code SecretKey} and
667
* associated entry attributes.
668
*
669
* <p> The specified {@code attributes} is cloned before it is stored
670
* in the new {@code SecretKeyEntry} object.
671
*
672
* @param secretKey the {@code SecretKey}
673
* @param attributes the attributes
674
*
675
* @throws NullPointerException if {@code secretKey} or
676
* {@code attributes} is {@code null}
677
*
678
* @since 1.8
679
*/
680
public SecretKeyEntry(SecretKey secretKey, Set<Attribute> attributes) {
681
682
if (secretKey == null || attributes == null) {
683
throw new NullPointerException("invalid null input");
684
}
685
this.sKey = secretKey;
686
this.attributes =
687
Collections.unmodifiableSet(new HashSet<>(attributes));
688
}
689
690
/**
691
* Gets the {@code SecretKey} from this entry.
692
*
693
* @return the {@code SecretKey} from this entry
694
*/
695
public SecretKey getSecretKey() {
696
return sKey;
697
}
698
699
/**
700
* Retrieves the attributes associated with an entry.
701
*
702
* @return an unmodifiable {@code Set} of attributes, possibly empty
703
*
704
* @since 1.8
705
*/
706
@Override
707
public Set<Attribute> getAttributes() {
708
return attributes;
709
}
710
711
/**
712
* Returns a string representation of this SecretKeyEntry.
713
* @return a string representation of this SecretKeyEntry.
714
*/
715
public String toString() {
716
return "Secret key entry with algorithm " + sKey.getAlgorithm();
717
}
718
}
719
720
/**
721
* A {@code KeyStore} entry that holds a trusted
722
* {@code Certificate}.
723
*
724
* @since 1.5
725
*/
726
public static final class TrustedCertificateEntry implements Entry {
727
728
private final Certificate cert;
729
private final Set<Attribute> attributes;
730
731
/**
732
* Constructs a {@code TrustedCertificateEntry} with a
733
* trusted {@code Certificate}.
734
*
735
* @param trustedCert the trusted {@code Certificate}
736
*
737
* @throws NullPointerException if
738
* {@code trustedCert} is {@code null}
739
*/
740
public TrustedCertificateEntry(Certificate trustedCert) {
741
if (trustedCert == null) {
742
throw new NullPointerException("invalid null input");
743
}
744
this.cert = trustedCert;
745
this.attributes = Collections.<Attribute>emptySet();
746
}
747
748
/**
749
* Constructs a {@code TrustedCertificateEntry} with a
750
* trusted {@code Certificate} and associated entry attributes.
751
*
752
* <p> The specified {@code attributes} is cloned before it is stored
753
* in the new {@code TrustedCertificateEntry} object.
754
*
755
* @param trustedCert the trusted {@code Certificate}
756
* @param attributes the attributes
757
*
758
* @throws NullPointerException if {@code trustedCert} or
759
* {@code attributes} is {@code null}
760
*
761
* @since 1.8
762
*/
763
public TrustedCertificateEntry(Certificate trustedCert,
764
Set<Attribute> attributes) {
765
if (trustedCert == null || attributes == null) {
766
throw new NullPointerException("invalid null input");
767
}
768
this.cert = trustedCert;
769
this.attributes =
770
Collections.unmodifiableSet(new HashSet<>(attributes));
771
}
772
773
/**
774
* Gets the trusted {@code Certficate} from this entry.
775
*
776
* @return the trusted {@code Certificate} from this entry
777
*/
778
public Certificate getTrustedCertificate() {
779
return cert;
780
}
781
782
/**
783
* Retrieves the attributes associated with an entry.
784
*
785
* @return an unmodifiable {@code Set} of attributes, possibly empty
786
*
787
* @since 1.8
788
*/
789
@Override
790
public Set<Attribute> getAttributes() {
791
return attributes;
792
}
793
794
/**
795
* Returns a string representation of this TrustedCertificateEntry.
796
* @return a string representation of this TrustedCertificateEntry.
797
*/
798
public String toString() {
799
return "Trusted certificate entry:\r\n" + cert.toString();
800
}
801
}
802
803
/**
804
* Creates a KeyStore object of the given type, and encapsulates the given
805
* provider implementation (SPI object) in it.
806
*
807
* @param keyStoreSpi the provider implementation.
808
* @param provider the provider.
809
* @param type the keystore type.
810
*/
811
protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)
812
{
813
this.keyStoreSpi = keyStoreSpi;
814
this.provider = provider;
815
this.type = type;
816
817
if (!skipDebug && pdebug != null) {
818
pdebug.println("KeyStore." + type.toUpperCase() + " type from: " +
819
getProviderName());
820
}
821
}
822
823
private String getProviderName() {
824
return (provider == null) ? "(no provider)" : provider.getName();
825
}
826
827
/**
828
* Returns a keystore object of the specified type.
829
*
830
* <p> This method traverses the list of registered security Providers,
831
* starting with the most preferred Provider.
832
* A new KeyStore object encapsulating the
833
* KeyStoreSpi implementation from the first
834
* Provider that supports the specified type is returned.
835
*
836
* <p> Note that the list of registered providers may be retrieved via
837
* the {@link Security#getProviders() Security.getProviders()} method.
838
*
839
* @implNote
840
* The JDK Reference Implementation additionally uses the
841
* {@code jdk.security.provider.preferred}
842
* {@link Security#getProperty(String) Security} property to determine
843
* the preferred provider order for the specified algorithm. This
844
* may be different than the order of providers returned by
845
* {@link Security#getProviders() Security.getProviders()}.
846
*
847
* @param type the type of keystore.
848
* See the KeyStore section in the <a href=
849
* "{@docRoot}/../specs/security/standard-names.html#keystore-types">
850
* Java Security Standard Algorithm Names Specification</a>
851
* for information about standard keystore types.
852
*
853
* @return a keystore object of the specified type
854
*
855
* @throws KeyStoreException if no {@code Provider} supports a
856
* {@code KeyStoreSpi} implementation for the
857
* specified type
858
*
859
* @throws NullPointerException if {@code type} is {@code null}
860
*
861
* @see Provider
862
*/
863
public static KeyStore getInstance(String type)
864
throws KeyStoreException
865
{
866
Objects.requireNonNull(type, "null type name");
867
try {
868
Object[] objs = Security.getImpl(type, "KeyStore", (String)null);
869
return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
870
} catch (NoSuchAlgorithmException nsae) {
871
throw new KeyStoreException(type + " not found", nsae);
872
} catch (NoSuchProviderException nspe) {
873
throw new KeyStoreException(type + " not found", nspe);
874
}
875
}
876
877
/**
878
* Returns a keystore object of the specified type.
879
*
880
* <p> A new KeyStore object encapsulating the
881
* KeyStoreSpi implementation from the specified provider
882
* is returned. The specified provider must be registered
883
* in the security provider list.
884
*
885
* <p> Note that the list of registered providers may be retrieved via
886
* the {@link Security#getProviders() Security.getProviders()} method.
887
*
888
* @param type the type of keystore.
889
* See the KeyStore section in the <a href=
890
* "{@docRoot}/../specs/security/standard-names.html#keystore-types">
891
* Java Security Standard Algorithm Names Specification</a>
892
* for information about standard keystore types.
893
*
894
* @param provider the name of the provider.
895
*
896
* @return a keystore object of the specified type
897
*
898
* @throws IllegalArgumentException if the provider name is {@code null}
899
* or empty
900
*
901
* @throws KeyStoreException if a {@code KeyStoreSpi}
902
* implementation for the specified type is not
903
* available from the specified provider
904
*
905
* @throws NoSuchProviderException if the specified provider is not
906
* registered in the security provider list
907
*
908
* @throws NullPointerException if {@code type} is {@code null}
909
*
910
* @see Provider
911
*/
912
public static KeyStore getInstance(String type, String provider)
913
throws KeyStoreException, NoSuchProviderException
914
{
915
Objects.requireNonNull(type, "null type name");
916
if (provider == null || provider.isEmpty())
917
throw new IllegalArgumentException("missing provider");
918
try {
919
Object[] objs = Security.getImpl(type, "KeyStore", provider);
920
return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
921
} catch (NoSuchAlgorithmException nsae) {
922
throw new KeyStoreException(type + " not found", nsae);
923
}
924
}
925
926
/**
927
* Returns a keystore object of the specified type.
928
*
929
* <p> A new KeyStore object encapsulating the
930
* KeyStoreSpi implementation from the specified Provider
931
* object is returned. Note that the specified Provider object
932
* does not have to be registered in the provider list.
933
*
934
* @param type the type of keystore.
935
* See the KeyStore section in the <a href=
936
* "{@docRoot}/../specs/security/standard-names.html#keystore-types">
937
* Java Security Standard Algorithm Names Specification</a>
938
* for information about standard keystore types.
939
*
940
* @param provider the provider.
941
*
942
* @return a keystore object of the specified type
943
*
944
* @throws IllegalArgumentException if the specified provider is
945
* {@code null}
946
*
947
* @throws KeyStoreException if {@code KeyStoreSpi}
948
* implementation for the specified type is not available
949
* from the specified {@code Provider} object
950
*
951
* @throws NullPointerException if {@code type} is {@code null}
952
*
953
* @see Provider
954
*
955
* @since 1.4
956
*/
957
public static KeyStore getInstance(String type, Provider provider)
958
throws KeyStoreException
959
{
960
Objects.requireNonNull(type, "null type name");
961
if (provider == null)
962
throw new IllegalArgumentException("missing provider");
963
try {
964
Object[] objs = Security.getImpl(type, "KeyStore", provider);
965
return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
966
} catch (NoSuchAlgorithmException nsae) {
967
throw new KeyStoreException(type + " not found", nsae);
968
}
969
}
970
971
/**
972
* Returns the default keystore type as specified by the
973
* {@code keystore.type} security property, or the string
974
* {@literal "jks"} (acronym for {@literal "Java keystore"})
975
* if no such property exists.
976
*
977
* <p>The default keystore type can be used by applications that do not
978
* want to use a hard-coded keystore type when calling one of the
979
* {@code getInstance} methods, and want to provide a default keystore
980
* type in case a user does not specify its own.
981
*
982
* <p>The default keystore type can be changed by setting the value of the
983
* {@code keystore.type} security property to the desired keystore type.
984
*
985
* @return the default keystore type as specified by the
986
* {@code keystore.type} security property, or the string {@literal "jks"}
987
* if no such property exists.
988
* @see java.security.Security security properties
989
*/
990
public static final String getDefaultType() {
991
@SuppressWarnings("removal")
992
String kstype = AccessController.doPrivileged(new PrivilegedAction<>() {
993
public String run() {
994
return Security.getProperty(KEYSTORE_TYPE);
995
}
996
});
997
if (kstype == null) {
998
kstype = "jks";
999
}
1000
return kstype;
1001
}
1002
1003
/**
1004
* Returns the provider of this keystore.
1005
*
1006
* @return the provider of this keystore.
1007
*/
1008
public final Provider getProvider()
1009
{
1010
return this.provider;
1011
}
1012
1013
/**
1014
* Returns the type of this keystore.
1015
*
1016
* @return the type of this keystore.
1017
*/
1018
public final String getType()
1019
{
1020
return this.type;
1021
}
1022
1023
/**
1024
* Returns the key associated with the given alias, using the given
1025
* password to recover it. The key must have been associated with
1026
* the alias by a call to {@code setKeyEntry},
1027
* or by a call to {@code setEntry} with a
1028
* {@code PrivateKeyEntry} or {@code SecretKeyEntry}.
1029
*
1030
* @param alias the alias name
1031
* @param password the password for recovering the key
1032
*
1033
* @return the requested key, or null if the given alias does not exist
1034
* or does not identify a key-related entry.
1035
*
1036
* @throws KeyStoreException if the keystore has not been initialized
1037
* (loaded).
1038
* @throws NoSuchAlgorithmException if the algorithm for recovering the
1039
* key cannot be found
1040
* @throws UnrecoverableKeyException if the key cannot be recovered
1041
* (e.g., the given password is wrong).
1042
*/
1043
public final Key getKey(String alias, char[] password)
1044
throws KeyStoreException, NoSuchAlgorithmException,
1045
UnrecoverableKeyException
1046
{
1047
if (!initialized) {
1048
throw new KeyStoreException("Uninitialized keystore");
1049
}
1050
return keyStoreSpi.engineGetKey(alias, password);
1051
}
1052
1053
/**
1054
* Returns the certificate chain associated with the given alias.
1055
* The certificate chain must have been associated with the alias
1056
* by a call to {@code setKeyEntry},
1057
* or by a call to {@code setEntry} with a
1058
* {@code PrivateKeyEntry}.
1059
*
1060
* @param alias the alias name
1061
*
1062
* @return the certificate chain (ordered with the user's certificate first
1063
* followed by zero or more certificate authorities), or null if the given alias
1064
* does not exist or does not contain a certificate chain
1065
*
1066
* @throws KeyStoreException if the keystore has not been initialized
1067
* (loaded).
1068
*/
1069
public final Certificate[] getCertificateChain(String alias)
1070
throws KeyStoreException
1071
{
1072
if (!initialized) {
1073
throw new KeyStoreException("Uninitialized keystore");
1074
}
1075
return keyStoreSpi.engineGetCertificateChain(alias);
1076
}
1077
1078
/**
1079
* Returns the certificate associated with the given alias.
1080
*
1081
* <p> If the given alias name identifies an entry
1082
* created by a call to {@code setCertificateEntry},
1083
* or created by a call to {@code setEntry} with a
1084
* {@code TrustedCertificateEntry},
1085
* then the trusted certificate contained in that entry is returned.
1086
*
1087
* <p> If the given alias name identifies an entry
1088
* created by a call to {@code setKeyEntry},
1089
* or created by a call to {@code setEntry} with a
1090
* {@code PrivateKeyEntry},
1091
* then the first element of the certificate chain in that entry
1092
* is returned.
1093
*
1094
* @param alias the alias name
1095
*
1096
* @return the certificate, or null if the given alias does not exist or
1097
* does not contain a certificate.
1098
*
1099
* @throws KeyStoreException if the keystore has not been initialized
1100
* (loaded).
1101
*/
1102
public final Certificate getCertificate(String alias)
1103
throws KeyStoreException
1104
{
1105
if (!initialized) {
1106
throw new KeyStoreException("Uninitialized keystore");
1107
}
1108
return keyStoreSpi.engineGetCertificate(alias);
1109
}
1110
1111
/**
1112
* Returns the creation date of the entry identified by the given alias.
1113
*
1114
* @param alias the alias name
1115
*
1116
* @return the creation date of this entry, or null if the given alias does
1117
* not exist
1118
*
1119
* @throws KeyStoreException if the keystore has not been initialized
1120
* (loaded).
1121
*/
1122
public final Date getCreationDate(String alias)
1123
throws KeyStoreException
1124
{
1125
if (!initialized) {
1126
throw new KeyStoreException("Uninitialized keystore");
1127
}
1128
return keyStoreSpi.engineGetCreationDate(alias);
1129
}
1130
1131
/**
1132
* Assigns the given key to the given alias, protecting it with the given
1133
* password.
1134
*
1135
* <p>If the given key is of type {@code java.security.PrivateKey},
1136
* it must be accompanied by a certificate chain certifying the
1137
* corresponding public key.
1138
*
1139
* <p>If the given alias already exists, the keystore information
1140
* associated with it is overridden by the given key (and possibly
1141
* certificate chain).
1142
*
1143
* @param alias the alias name
1144
* @param key the key to be associated with the alias
1145
* @param password the password to protect the key
1146
* @param chain the certificate chain for the corresponding public
1147
* key (only required if the given key is of type
1148
* {@code java.security.PrivateKey}).
1149
*
1150
* @throws KeyStoreException if the keystore has not been initialized
1151
* (loaded), the given key cannot be protected, or this operation fails
1152
* for some other reason
1153
*/
1154
public final void setKeyEntry(String alias, Key key, char[] password,
1155
Certificate[] chain)
1156
throws KeyStoreException
1157
{
1158
if (!initialized) {
1159
throw new KeyStoreException("Uninitialized keystore");
1160
}
1161
if ((key instanceof PrivateKey) &&
1162
(chain == null || chain.length == 0)) {
1163
throw new IllegalArgumentException("Private key must be "
1164
+ "accompanied by certificate "
1165
+ "chain");
1166
}
1167
keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
1168
}
1169
1170
/**
1171
* Assigns the given key (that has already been protected) to the given
1172
* alias.
1173
*
1174
* <p>If the protected key is of type
1175
* {@code java.security.PrivateKey}, it must be accompanied by a
1176
* certificate chain certifying the corresponding public key. If the
1177
* underlying keystore implementation is of type {@code jks},
1178
* {@code key} must be encoded as an
1179
* {@code EncryptedPrivateKeyInfo} as defined in the PKCS #8 standard.
1180
*
1181
* <p>If the given alias already exists, the keystore information
1182
* associated with it is overridden by the given key (and possibly
1183
* certificate chain).
1184
*
1185
* @param alias the alias name
1186
* @param key the key (in protected format) to be associated with the alias
1187
* @param chain the certificate chain for the corresponding public
1188
* key (only useful if the protected key is of type
1189
* {@code java.security.PrivateKey}).
1190
*
1191
* @throws KeyStoreException if the keystore has not been initialized
1192
* (loaded), or if this operation fails for some other reason.
1193
*/
1194
public final void setKeyEntry(String alias, byte[] key,
1195
Certificate[] chain)
1196
throws KeyStoreException
1197
{
1198
if (!initialized) {
1199
throw new KeyStoreException("Uninitialized keystore");
1200
}
1201
keyStoreSpi.engineSetKeyEntry(alias, key, chain);
1202
}
1203
1204
/**
1205
* Assigns the given trusted certificate to the given alias.
1206
*
1207
* <p> If the given alias identifies an existing entry
1208
* created by a call to {@code setCertificateEntry},
1209
* or created by a call to {@code setEntry} with a
1210
* {@code TrustedCertificateEntry},
1211
* the trusted certificate in the existing entry
1212
* is overridden by the given certificate.
1213
*
1214
* @param alias the alias name
1215
* @param cert the certificate
1216
*
1217
* @throws KeyStoreException if the keystore has not been initialized,
1218
* or the given alias already exists and does not identify an
1219
* entry containing a trusted certificate,
1220
* or this operation fails for some other reason.
1221
*/
1222
public final void setCertificateEntry(String alias, Certificate cert)
1223
throws KeyStoreException
1224
{
1225
if (!initialized) {
1226
throw new KeyStoreException("Uninitialized keystore");
1227
}
1228
keyStoreSpi.engineSetCertificateEntry(alias, cert);
1229
}
1230
1231
/**
1232
* Deletes the entry identified by the given alias from this keystore.
1233
*
1234
* @param alias the alias name
1235
*
1236
* @throws KeyStoreException if the keystore has not been initialized,
1237
* or if the entry cannot be removed.
1238
*/
1239
public final void deleteEntry(String alias)
1240
throws KeyStoreException
1241
{
1242
if (!initialized) {
1243
throw new KeyStoreException("Uninitialized keystore");
1244
}
1245
keyStoreSpi.engineDeleteEntry(alias);
1246
}
1247
1248
/**
1249
* Lists all the alias names of this keystore.
1250
*
1251
* @return enumeration of the alias names
1252
*
1253
* @throws KeyStoreException if the keystore has not been initialized
1254
* (loaded).
1255
*/
1256
public final Enumeration<String> aliases()
1257
throws KeyStoreException
1258
{
1259
if (!initialized) {
1260
throw new KeyStoreException("Uninitialized keystore");
1261
}
1262
return keyStoreSpi.engineAliases();
1263
}
1264
1265
/**
1266
* Checks if the given alias exists in this keystore.
1267
*
1268
* @param alias the alias name
1269
*
1270
* @return true if the alias exists, false otherwise
1271
*
1272
* @throws KeyStoreException if the keystore has not been initialized
1273
* (loaded).
1274
*/
1275
public final boolean containsAlias(String alias)
1276
throws KeyStoreException
1277
{
1278
if (!initialized) {
1279
throw new KeyStoreException("Uninitialized keystore");
1280
}
1281
return keyStoreSpi.engineContainsAlias(alias);
1282
}
1283
1284
/**
1285
* Retrieves the number of entries in this keystore.
1286
*
1287
* @return the number of entries in this keystore
1288
*
1289
* @throws KeyStoreException if the keystore has not been initialized
1290
* (loaded).
1291
*/
1292
public final int size()
1293
throws KeyStoreException
1294
{
1295
if (!initialized) {
1296
throw new KeyStoreException("Uninitialized keystore");
1297
}
1298
return keyStoreSpi.engineSize();
1299
}
1300
1301
/**
1302
* Returns true if the entry identified by the given alias
1303
* was created by a call to {@code setKeyEntry},
1304
* or created by a call to {@code setEntry} with a
1305
* {@code PrivateKeyEntry} or a {@code SecretKeyEntry}.
1306
*
1307
* @param alias the alias for the keystore entry to be checked
1308
*
1309
* @return true if the entry identified by the given alias is a
1310
* key-related entry, false otherwise.
1311
*
1312
* @throws KeyStoreException if the keystore has not been initialized
1313
* (loaded).
1314
*/
1315
public final boolean isKeyEntry(String alias)
1316
throws KeyStoreException
1317
{
1318
if (!initialized) {
1319
throw new KeyStoreException("Uninitialized keystore");
1320
}
1321
return keyStoreSpi.engineIsKeyEntry(alias);
1322
}
1323
1324
/**
1325
* Returns true if the entry identified by the given alias
1326
* was created by a call to {@code setCertificateEntry},
1327
* or created by a call to {@code setEntry} with a
1328
* {@code TrustedCertificateEntry}.
1329
*
1330
* @param alias the alias for the keystore entry to be checked
1331
*
1332
* @return true if the entry identified by the given alias contains a
1333
* trusted certificate, false otherwise.
1334
*
1335
* @throws KeyStoreException if the keystore has not been initialized
1336
* (loaded).
1337
*/
1338
public final boolean isCertificateEntry(String alias)
1339
throws KeyStoreException
1340
{
1341
if (!initialized) {
1342
throw new KeyStoreException("Uninitialized keystore");
1343
}
1344
return keyStoreSpi.engineIsCertificateEntry(alias);
1345
}
1346
1347
/**
1348
* Returns the (alias) name of the first keystore entry whose certificate
1349
* matches the given certificate.
1350
*
1351
* <p> This method attempts to match the given certificate with each
1352
* keystore entry. If the entry being considered was
1353
* created by a call to {@code setCertificateEntry},
1354
* or created by a call to {@code setEntry} with a
1355
* {@code TrustedCertificateEntry},
1356
* then the given certificate is compared to that entry's certificate.
1357
*
1358
* <p> If the entry being considered was
1359
* created by a call to {@code setKeyEntry},
1360
* or created by a call to {@code setEntry} with a
1361
* {@code PrivateKeyEntry},
1362
* then the given certificate is compared to the first
1363
* element of that entry's certificate chain.
1364
*
1365
* @param cert the certificate to match with.
1366
*
1367
* @return the alias name of the first entry with a matching certificate,
1368
* or null if no such entry exists in this keystore.
1369
*
1370
* @throws KeyStoreException if the keystore has not been initialized
1371
* (loaded).
1372
*/
1373
public final String getCertificateAlias(Certificate cert)
1374
throws KeyStoreException
1375
{
1376
if (!initialized) {
1377
throw new KeyStoreException("Uninitialized keystore");
1378
}
1379
return keyStoreSpi.engineGetCertificateAlias(cert);
1380
}
1381
1382
/**
1383
* Stores this keystore to the given output stream, and protects its
1384
* integrity with the given password.
1385
*
1386
* @param stream the output stream to which this keystore is written.
1387
* @param password the password to generate the keystore integrity check
1388
*
1389
* @throws KeyStoreException if the keystore has not been initialized
1390
* (loaded).
1391
* @throws IOException if there was an I/O problem with data
1392
* @throws NoSuchAlgorithmException if the appropriate data integrity
1393
* algorithm could not be found
1394
* @throws CertificateException if any of the certificates included in
1395
* the keystore data could not be stored
1396
*/
1397
public final void store(OutputStream stream, char[] password)
1398
throws KeyStoreException, IOException, NoSuchAlgorithmException,
1399
CertificateException
1400
{
1401
if (!initialized) {
1402
throw new KeyStoreException("Uninitialized keystore");
1403
}
1404
keyStoreSpi.engineStore(stream, password);
1405
}
1406
1407
/**
1408
* Stores this keystore using the given {@code LoadStoreParameter}.
1409
*
1410
* @param param the {@code LoadStoreParameter}
1411
* that specifies how to store the keystore,
1412
* which may be {@code null}
1413
*
1414
* @throws IllegalArgumentException if the given
1415
* {@code LoadStoreParameter}
1416
* input is not recognized
1417
* @throws KeyStoreException if the keystore has not been initialized
1418
* (loaded)
1419
* @throws IOException if there was an I/O problem with data
1420
* @throws NoSuchAlgorithmException if the appropriate data integrity
1421
* algorithm could not be found
1422
* @throws CertificateException if any of the certificates included in
1423
* the keystore data could not be stored
1424
* @throws UnsupportedOperationException if this operation is not supported
1425
*
1426
* @since 1.5
1427
*/
1428
public final void store(LoadStoreParameter param)
1429
throws KeyStoreException, IOException,
1430
NoSuchAlgorithmException, CertificateException {
1431
if (!initialized) {
1432
throw new KeyStoreException("Uninitialized keystore");
1433
}
1434
keyStoreSpi.engineStore(param);
1435
}
1436
1437
/**
1438
* Loads this KeyStore from the given input stream.
1439
*
1440
* <p>A password may be given to unlock the keystore
1441
* (e.g. the keystore resides on a hardware token device),
1442
* or to check the integrity of the keystore data.
1443
* If a password is not given for integrity checking,
1444
* then integrity checking is not performed.
1445
*
1446
* <p>In order to create an empty keystore, or if the keystore cannot
1447
* be initialized from a stream, pass {@code null}
1448
* as the {@code stream} argument.
1449
*
1450
* <p> Note that if this keystore has already been loaded, it is
1451
* reinitialized and loaded again from the given input stream.
1452
*
1453
* @param stream the input stream from which the keystore is loaded,
1454
* or {@code null}
1455
* @param password the password used to check the integrity of
1456
* the keystore, the password used to unlock the keystore,
1457
* or {@code null}
1458
*
1459
* @throws IOException if there is an I/O or format problem with the
1460
* keystore data, if a password is required but not given,
1461
* or if the given password was incorrect. If the error is due to a
1462
* wrong password, the {@link Throwable#getCause cause} of the
1463
* {@code IOException} should be an
1464
* {@code UnrecoverableKeyException}
1465
* @throws NoSuchAlgorithmException if the algorithm used to check
1466
* the integrity of the keystore cannot be found
1467
* @throws CertificateException if any of the certificates in the
1468
* keystore could not be loaded
1469
*/
1470
public final void load(InputStream stream, char[] password)
1471
throws IOException, NoSuchAlgorithmException, CertificateException
1472
{
1473
keyStoreSpi.engineLoad(stream, password);
1474
initialized = true;
1475
}
1476
1477
/**
1478
* Loads this keystore using the given {@code LoadStoreParameter}.
1479
*
1480
* <p> Note that if this KeyStore has already been loaded, it is
1481
* reinitialized and loaded again from the given parameter.
1482
*
1483
* @param param the {@code LoadStoreParameter}
1484
* that specifies how to load the keystore,
1485
* which may be {@code null}
1486
*
1487
* @throws IllegalArgumentException if the given
1488
* {@code LoadStoreParameter}
1489
* input is not recognized
1490
* @throws IOException if there is an I/O or format problem with the
1491
* keystore data. If the error is due to an incorrect
1492
* {@code ProtectionParameter} (e.g. wrong password)
1493
* the {@link Throwable#getCause cause} of the
1494
* {@code IOException} should be an
1495
* {@code UnrecoverableKeyException}
1496
* @throws NoSuchAlgorithmException if the algorithm used to check
1497
* the integrity of the keystore cannot be found
1498
* @throws CertificateException if any of the certificates in the
1499
* keystore could not be loaded
1500
*
1501
* @since 1.5
1502
*/
1503
public final void load(LoadStoreParameter param)
1504
throws IOException, NoSuchAlgorithmException,
1505
CertificateException {
1506
1507
keyStoreSpi.engineLoad(param);
1508
initialized = true;
1509
}
1510
1511
/**
1512
* Gets a keystore {@code Entry} for the specified alias
1513
* with the specified protection parameter.
1514
*
1515
* @param alias get the keystore {@code Entry} for this alias
1516
* @param protParam the {@code ProtectionParameter}
1517
* used to protect the {@code Entry},
1518
* which may be {@code null}
1519
*
1520
* @return the keystore {@code Entry} for the specified alias,
1521
* or {@code null} if there is no such entry
1522
*
1523
* @throws NullPointerException if
1524
* {@code alias} is {@code null}
1525
* @throws NoSuchAlgorithmException if the algorithm for recovering the
1526
* entry cannot be found
1527
* @throws UnrecoverableEntryException if the specified
1528
* {@code protParam} were insufficient or invalid
1529
* @throws UnrecoverableKeyException if the entry is a
1530
* {@code PrivateKeyEntry} or {@code SecretKeyEntry}
1531
* and the specified {@code protParam} does not contain
1532
* the information needed to recover the key (e.g. wrong password)
1533
* @throws KeyStoreException if the keystore has not been initialized
1534
* (loaded).
1535
* @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter)
1536
*
1537
* @since 1.5
1538
*/
1539
public final Entry getEntry(String alias, ProtectionParameter protParam)
1540
throws NoSuchAlgorithmException, UnrecoverableEntryException,
1541
KeyStoreException {
1542
1543
if (alias == null) {
1544
throw new NullPointerException("invalid null input");
1545
}
1546
if (!initialized) {
1547
throw new KeyStoreException("Uninitialized keystore");
1548
}
1549
return keyStoreSpi.engineGetEntry(alias, protParam);
1550
}
1551
1552
/**
1553
* Saves a keystore {@code Entry} under the specified alias.
1554
* The protection parameter is used to protect the
1555
* {@code Entry}.
1556
*
1557
* <p> If an entry already exists for the specified alias,
1558
* it is overridden.
1559
*
1560
* @param alias save the keystore {@code Entry} under this alias
1561
* @param entry the {@code Entry} to save
1562
* @param protParam the {@code ProtectionParameter}
1563
* used to protect the {@code Entry},
1564
* which may be {@code null}
1565
*
1566
* @throws NullPointerException if
1567
* {@code alias} or {@code entry}
1568
* is {@code null}
1569
* @throws KeyStoreException if the keystore has not been initialized
1570
* (loaded), or if this operation fails for some other reason
1571
*
1572
* @see #getEntry(String, KeyStore.ProtectionParameter)
1573
*
1574
* @since 1.5
1575
*/
1576
public final void setEntry(String alias, Entry entry,
1577
ProtectionParameter protParam)
1578
throws KeyStoreException {
1579
if (alias == null || entry == null) {
1580
throw new NullPointerException("invalid null input");
1581
}
1582
if (!initialized) {
1583
throw new KeyStoreException("Uninitialized keystore");
1584
}
1585
keyStoreSpi.engineSetEntry(alias, entry, protParam);
1586
}
1587
1588
/**
1589
* Determines if the keystore {@code Entry} for the specified
1590
* {@code alias} is an instance or subclass of the specified
1591
* {@code entryClass}.
1592
*
1593
* @param alias the alias name
1594
* @param entryClass the entry class
1595
*
1596
* @return true if the keystore {@code Entry} for the specified
1597
* {@code alias} is an instance or subclass of the
1598
* specified {@code entryClass}, false otherwise
1599
*
1600
* @throws NullPointerException if
1601
* {@code alias} or {@code entryClass}
1602
* is {@code null}
1603
* @throws KeyStoreException if the keystore has not been
1604
* initialized (loaded)
1605
*
1606
* @since 1.5
1607
*/
1608
public final boolean
1609
entryInstanceOf(String alias,
1610
Class<? extends KeyStore.Entry> entryClass)
1611
throws KeyStoreException
1612
{
1613
1614
if (alias == null || entryClass == null) {
1615
throw new NullPointerException("invalid null input");
1616
}
1617
if (!initialized) {
1618
throw new KeyStoreException("Uninitialized keystore");
1619
}
1620
return keyStoreSpi.engineEntryInstanceOf(alias, entryClass);
1621
}
1622
1623
/**
1624
* Returns a loaded keystore object of the appropriate keystore type.
1625
* First the keystore type is determined by probing the specified file.
1626
* Then a keystore object is instantiated and loaded using the data from
1627
* that file.
1628
*
1629
* <p>
1630
* A password may be given to unlock the keystore
1631
* (e.g. the keystore resides on a hardware token device),
1632
* or to check the integrity of the keystore data.
1633
* If a password is not given for integrity checking,
1634
* then integrity checking is not performed.
1635
*
1636
* <p>
1637
* This method traverses the list of registered security
1638
* {@linkplain Provider providers}, starting with the most
1639
* preferred Provider.
1640
* For each {@link KeyStoreSpi} implementation supported by a
1641
* Provider, it invokes the {@link
1642
* KeyStoreSpi#engineProbe(InputStream) engineProbe} method to
1643
* determine if it supports the specified keystore.
1644
* A new KeyStore object is returned that encapsulates the KeyStoreSpi
1645
* implementation from the first Provider that supports the specified file.
1646
*
1647
* <p> Note that the list of registered providers may be retrieved via
1648
* the {@link Security#getProviders() Security.getProviders()} method.
1649
*
1650
* @param file the keystore file
1651
* @param password the keystore password, which may be {@code null}
1652
*
1653
* @return a keystore object loaded with keystore data
1654
*
1655
* @throws KeyStoreException if no Provider supports a KeyStoreSpi
1656
* implementation for the specified keystore file.
1657
* @throws IOException if there is an I/O or format problem with the
1658
* keystore data, if a password is required but not given,
1659
* or if the given password was incorrect. If the error is
1660
* due to a wrong password, the {@link Throwable#getCause cause}
1661
* of the {@code IOException} should be an
1662
* {@code UnrecoverableKeyException}.
1663
* @throws NoSuchAlgorithmException if the algorithm used to check the
1664
* integrity of the keystore cannot be found.
1665
* @throws CertificateException if any of the certificates in the
1666
* keystore could not be loaded.
1667
* @throws IllegalArgumentException if file does not exist or does not
1668
* refer to a normal file.
1669
* @throws NullPointerException if file is {@code null}.
1670
* @throws SecurityException if a security manager exists and its
1671
* {@link java.lang.SecurityManager#checkRead} method denies
1672
* read access to the specified file.
1673
*
1674
* @see Provider
1675
*
1676
* @since 9
1677
*/
1678
public static final KeyStore getInstance(File file, char[] password)
1679
throws KeyStoreException, IOException, NoSuchAlgorithmException,
1680
CertificateException {
1681
return getInstance(file, password, null, true);
1682
}
1683
1684
/**
1685
* Returns a loaded keystore object of the appropriate keystore type.
1686
* First the keystore type is determined by probing the specified file.
1687
* Then a keystore object is instantiated and loaded using the data from
1688
* that file.
1689
* A {@code LoadStoreParameter} may be supplied which specifies how to
1690
* unlock the keystore data or perform an integrity check.
1691
*
1692
* <p>
1693
* This method traverses the list of registered security {@linkplain
1694
* Provider providers}, starting with the most preferred Provider.
1695
* For each {@link KeyStoreSpi} implementation supported by a
1696
* Provider, it invokes the {@link
1697
* KeyStoreSpi#engineProbe(InputStream) engineProbe} method to
1698
* determine if it supports the specified keystore.
1699
* A new KeyStore object is returned that encapsulates the KeyStoreSpi
1700
* implementation from the first Provider that supports the specified file.
1701
*
1702
* <p> Note that the list of registered providers may be retrieved via
1703
* the {@link Security#getProviders() Security.getProviders()} method.
1704
*
1705
* @param file the keystore file
1706
* @param param the {@code LoadStoreParameter} that specifies how to load
1707
* the keystore, which may be {@code null}
1708
*
1709
* @return a keystore object loaded with keystore data
1710
*
1711
* @throws KeyStoreException if no Provider supports a KeyStoreSpi
1712
* implementation for the specified keystore file.
1713
* @throws IOException if there is an I/O or format problem with the
1714
* keystore data. If the error is due to an incorrect
1715
* {@code ProtectionParameter} (e.g. wrong password)
1716
* the {@link Throwable#getCause cause} of the
1717
* {@code IOException} should be an
1718
* {@code UnrecoverableKeyException}.
1719
* @throws NoSuchAlgorithmException if the algorithm used to check the
1720
* integrity of the keystore cannot be found.
1721
* @throws CertificateException if any of the certificates in the
1722
* keystore could not be loaded.
1723
* @throws IllegalArgumentException if file does not exist or does not
1724
* refer to a normal file, or if param is not recognized.
1725
* @throws NullPointerException if file is {@code null}.
1726
* @throws SecurityException if a security manager exists and its
1727
* {@link java.lang.SecurityManager#checkRead} method denies
1728
* read access to the specified file.
1729
*
1730
* @see Provider
1731
*
1732
* @since 9
1733
*/
1734
public static final KeyStore getInstance(File file,
1735
LoadStoreParameter param) throws KeyStoreException, IOException,
1736
NoSuchAlgorithmException, CertificateException {
1737
return getInstance(file, null, param, false);
1738
}
1739
1740
// Used by getInstance(File, char[]) & getInstance(File, LoadStoreParameter)
1741
private static final KeyStore getInstance(File file, char[] password,
1742
LoadStoreParameter param, boolean hasPassword)
1743
throws KeyStoreException, IOException, NoSuchAlgorithmException,
1744
CertificateException {
1745
1746
if (file == null) {
1747
throw new NullPointerException();
1748
}
1749
1750
if (file.isFile() == false) {
1751
throw new IllegalArgumentException(
1752
"File does not exist or it does not refer to a normal file: " +
1753
file);
1754
}
1755
1756
KeyStore keystore = null;
1757
1758
try (DataInputStream dataStream =
1759
new DataInputStream(
1760
new BufferedInputStream(
1761
new FileInputStream(file)))) {
1762
1763
dataStream.mark(Integer.MAX_VALUE);
1764
1765
// Detect the keystore type
1766
for (Provider p : Security.getProviders()) {
1767
for (Provider.Service s : p.getServices()) {
1768
if (s.getType().equals("KeyStore")) {
1769
try {
1770
KeyStoreSpi impl = (KeyStoreSpi) s.newInstance(null);
1771
if (impl.engineProbe(dataStream)) {
1772
if (kdebug != null) {
1773
kdebug.println(s.getAlgorithm()
1774
+ " keystore detected: " + file);
1775
}
1776
keystore = new KeyStore(impl, p, s.getAlgorithm());
1777
break;
1778
}
1779
} catch (NoSuchAlgorithmException e) {
1780
// ignore
1781
if (kdebug != null) {
1782
kdebug.println("not found - " + e);
1783
}
1784
} catch (IOException e) {
1785
// ignore
1786
if (kdebug != null) {
1787
kdebug.println("I/O error in " + file + " - " + e);
1788
}
1789
}
1790
dataStream.reset(); // prepare the stream for the next probe
1791
}
1792
}
1793
}
1794
1795
// Load the keystore data
1796
if (keystore != null) {
1797
dataStream.reset(); // prepare the stream for loading
1798
if (hasPassword) {
1799
keystore.load(dataStream, password);
1800
} else {
1801
keystore.keyStoreSpi.engineLoad(dataStream, param);
1802
keystore.initialized = true;
1803
}
1804
return keystore;
1805
}
1806
}
1807
1808
throw new KeyStoreException("Unrecognized keystore format. "
1809
+ "Please load it with a specified type");
1810
}
1811
1812
/**
1813
* A description of a to-be-instantiated KeyStore object.
1814
*
1815
* <p>An instance of this class encapsulates the information needed to
1816
* instantiate and initialize a KeyStore object. That process is
1817
* triggered when the {@linkplain #getKeyStore} method is called.
1818
*
1819
* <p>This makes it possible to decouple configuration from KeyStore
1820
* object creation and e.g. delay a password prompt until it is
1821
* needed.
1822
*
1823
* @see KeyStore
1824
* @see javax.net.ssl.KeyStoreBuilderParameters
1825
* @since 1.5
1826
*/
1827
public abstract static class Builder {
1828
1829
// maximum times to try the callbackhandler if the password is wrong
1830
static final int MAX_CALLBACK_TRIES = 3;
1831
1832
/**
1833
* Construct a new Builder.
1834
*/
1835
protected Builder() {
1836
// empty
1837
}
1838
1839
/**
1840
* Returns the KeyStore described by this object.
1841
*
1842
* @return the {@code KeyStore} described by this object
1843
* @throws KeyStoreException if an error occurred during the
1844
* operation, for example if the KeyStore could not be
1845
* instantiated or loaded
1846
*/
1847
public abstract KeyStore getKeyStore() throws KeyStoreException;
1848
1849
/**
1850
* Returns the ProtectionParameters that should be used to obtain
1851
* the {@link KeyStore.Entry Entry} with the given alias.
1852
* The {@code getKeyStore} method must be invoked before this
1853
* method may be called.
1854
*
1855
* @return the ProtectionParameters that should be used to obtain
1856
* the {@link KeyStore.Entry Entry} with the given alias.
1857
* @param alias the alias of the KeyStore entry
1858
* @throws NullPointerException if alias is null
1859
* @throws KeyStoreException if an error occurred during the
1860
* operation
1861
* @throws IllegalStateException if the getKeyStore method has
1862
* not been invoked prior to calling this method
1863
*/
1864
public abstract ProtectionParameter getProtectionParameter(String alias)
1865
throws KeyStoreException;
1866
1867
/**
1868
* Returns a new Builder that encapsulates the given KeyStore.
1869
* The {@linkplain #getKeyStore} method of the returned object
1870
* will return {@code keyStore}, the {@linkplain
1871
* #getProtectionParameter getProtectionParameter()} method will
1872
* return {@code protectionParameters}.
1873
*
1874
* <p> This is useful if an existing KeyStore object needs to be
1875
* used with Builder-based APIs.
1876
*
1877
* @return a new Builder object
1878
* @param keyStore the KeyStore to be encapsulated
1879
* @param protectionParameter the ProtectionParameter used to
1880
* protect the KeyStore entries
1881
* @throws NullPointerException if keyStore or
1882
* protectionParameters is null
1883
* @throws IllegalArgumentException if the keyStore has not been
1884
* initialized
1885
*/
1886
public static Builder newInstance(final KeyStore keyStore,
1887
final ProtectionParameter protectionParameter) {
1888
if ((keyStore == null) || (protectionParameter == null)) {
1889
throw new NullPointerException();
1890
}
1891
if (keyStore.initialized == false) {
1892
throw new IllegalArgumentException("KeyStore not initialized");
1893
}
1894
return new Builder() {
1895
private volatile boolean getCalled;
1896
1897
public KeyStore getKeyStore() {
1898
getCalled = true;
1899
return keyStore;
1900
}
1901
1902
public ProtectionParameter getProtectionParameter(String alias)
1903
{
1904
if (alias == null) {
1905
throw new NullPointerException();
1906
}
1907
if (getCalled == false) {
1908
throw new IllegalStateException
1909
("getKeyStore() must be called first");
1910
}
1911
return protectionParameter;
1912
}
1913
};
1914
}
1915
1916
/**
1917
* Returns a new Builder object.
1918
*
1919
* <p>The first call to the {@link #getKeyStore} method on the returned
1920
* builder will create a KeyStore of type {@code type} and call
1921
* its {@link KeyStore#load load()} method.
1922
* The {@code inputStream} argument is constructed from
1923
* {@code file}.
1924
* If {@code protection} is a
1925
* {@code PasswordProtection}, the password is obtained by
1926
* calling the {@code getPassword} method.
1927
* Otherwise, if {@code protection} is a
1928
* {@code CallbackHandlerProtection}, the password is obtained
1929
* by invoking the CallbackHandler.
1930
*
1931
* <p>Subsequent calls to {@link #getKeyStore} return the same object
1932
* as the initial call. If the initial call failed with a
1933
* KeyStoreException, subsequent calls also throw a
1934
* KeyStoreException.
1935
*
1936
* <p>The KeyStore is instantiated from {@code provider} if
1937
* non-null. Otherwise, all installed providers are searched.
1938
*
1939
* <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
1940
* will return a {@link KeyStore.PasswordProtection PasswordProtection}
1941
* object encapsulating the password that was used to invoke the
1942
* {@code load} method.
1943
*
1944
* <p><em>Note</em> that the {@link #getKeyStore} method is executed
1945
* within the {@link AccessControlContext} of the code invoking this
1946
* method.
1947
*
1948
* @return a new Builder object
1949
* @param type the type of KeyStore to be constructed
1950
* @param provider the provider from which the KeyStore is to
1951
* be instantiated (or null)
1952
* @param file the File that contains the KeyStore data
1953
* @param protection the ProtectionParameter securing the KeyStore data
1954
* @throws NullPointerException if type, file or protection is null
1955
* @throws IllegalArgumentException if protection is not an instance
1956
* of either PasswordProtection or CallbackHandlerProtection; or
1957
* if file does not exist or does not refer to a normal file
1958
*/
1959
public static Builder newInstance(String type, Provider provider,
1960
File file, ProtectionParameter protection) {
1961
if ((type == null) || (file == null) || (protection == null)) {
1962
throw new NullPointerException();
1963
}
1964
if (!(protection instanceof PasswordProtection) &&
1965
!(protection instanceof CallbackHandlerProtection)) {
1966
throw new IllegalArgumentException
1967
("Protection must be PasswordProtection or " +
1968
"CallbackHandlerProtection");
1969
}
1970
if (!file.isFile()) {
1971
throw new IllegalArgumentException
1972
("File does not exist or it does not refer " +
1973
"to a normal file: " + file);
1974
}
1975
@SuppressWarnings("removal")
1976
var acc = AccessController.getContext();
1977
return new FileBuilder(type, provider, file, protection, acc);
1978
}
1979
1980
/**
1981
* Returns a new Builder object.
1982
*
1983
* <p>The first call to the {@link #getKeyStore} method on the returned
1984
* builder will create a KeyStore using {@code file} to detect the
1985
* keystore type and then call its {@link KeyStore#load load()} method.
1986
* It uses the same algorithm to determine the keystore type as
1987
* described in {@link KeyStore#getInstance(File, LoadStoreParameter)}.
1988
* The {@code inputStream} argument is constructed from {@code file}.
1989
* If {@code protection} is a {@code PasswordProtection}, the password
1990
* is obtained by calling the {@code getPassword} method.
1991
* Otherwise, if {@code protection} is a
1992
* {@code CallbackHandlerProtection},
1993
* the password is obtained by invoking the CallbackHandler.
1994
*
1995
* <p>Subsequent calls to {@link #getKeyStore} return the same object
1996
* as the initial call. If the initial call failed with a
1997
* KeyStoreException, subsequent calls also throw a KeyStoreException.
1998
*
1999
* <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
2000
* will return a {@link KeyStore.PasswordProtection PasswordProtection}
2001
* object encapsulating the password that was used to invoke the
2002
* {@code load} method.
2003
*
2004
* <p><em>Note</em> that the {@link #getKeyStore} method is executed
2005
* within the {@link AccessControlContext} of the code invoking this
2006
* method.
2007
*
2008
* @return a new Builder object
2009
* @param file the File that contains the KeyStore data
2010
* @param protection the ProtectionParameter securing the KeyStore data
2011
* @throws NullPointerException if file or protection is null
2012
* @throws IllegalArgumentException if protection is not an instance
2013
* of either PasswordProtection or CallbackHandlerProtection; or
2014
* if file does not exist or does not refer to a normal file
2015
*
2016
* @since 9
2017
*/
2018
public static Builder newInstance(File file,
2019
ProtectionParameter protection) {
2020
2021
return newInstance("", null, file, protection);
2022
}
2023
2024
private static final class FileBuilder extends Builder {
2025
2026
private final String type;
2027
private final Provider provider;
2028
private final File file;
2029
private ProtectionParameter protection;
2030
private ProtectionParameter keyProtection;
2031
@SuppressWarnings("removal")
2032
private final AccessControlContext context;
2033
2034
private KeyStore keyStore;
2035
2036
private Throwable oldException;
2037
2038
FileBuilder(String type, Provider provider, File file,
2039
ProtectionParameter protection,
2040
@SuppressWarnings("removal") AccessControlContext context) {
2041
this.type = type;
2042
this.provider = provider;
2043
this.file = file;
2044
this.protection = protection;
2045
this.context = context;
2046
}
2047
2048
@SuppressWarnings("removal")
2049
public synchronized KeyStore getKeyStore() throws KeyStoreException
2050
{
2051
if (keyStore != null) {
2052
return keyStore;
2053
}
2054
if (oldException != null) {
2055
throw new KeyStoreException
2056
("Previous KeyStore instantiation failed",
2057
oldException);
2058
}
2059
PrivilegedExceptionAction<KeyStore> action =
2060
new PrivilegedExceptionAction<KeyStore>() {
2061
public KeyStore run() throws Exception {
2062
if (!(protection instanceof CallbackHandlerProtection)) {
2063
return run0();
2064
}
2065
// when using a CallbackHandler,
2066
// reprompt if the password is wrong
2067
int tries = 0;
2068
while (true) {
2069
tries++;
2070
try {
2071
return run0();
2072
} catch (IOException e) {
2073
if ((tries < MAX_CALLBACK_TRIES)
2074
&& (e.getCause() instanceof UnrecoverableKeyException)) {
2075
continue;
2076
}
2077
throw e;
2078
}
2079
}
2080
}
2081
public KeyStore run0() throws Exception {
2082
KeyStore ks;
2083
char[] password = null;
2084
2085
// Acquire keystore password
2086
if (protection instanceof PasswordProtection) {
2087
password =
2088
((PasswordProtection)protection).getPassword();
2089
keyProtection = protection;
2090
} else {
2091
CallbackHandler handler =
2092
((CallbackHandlerProtection)protection)
2093
.getCallbackHandler();
2094
PasswordCallback callback = new PasswordCallback
2095
("Password for keystore " + file.getName(),
2096
false);
2097
handler.handle(new Callback[] {callback});
2098
password = callback.getPassword();
2099
if (password == null) {
2100
throw new KeyStoreException("No password" +
2101
" provided");
2102
}
2103
callback.clearPassword();
2104
keyProtection = new PasswordProtection(password);
2105
}
2106
2107
if (type.isEmpty()) {
2108
// Instantiate keystore and load keystore data
2109
ks = KeyStore.getInstance(file, password);
2110
} else {
2111
// Instantiate keystore
2112
if (provider == null) {
2113
ks = KeyStore.getInstance(type);
2114
} else {
2115
ks = KeyStore.getInstance(type, provider);
2116
}
2117
// Load keystore data
2118
try (InputStream in = new FileInputStream(file)) {
2119
ks.load(in, password);
2120
}
2121
}
2122
return ks;
2123
}
2124
};
2125
try {
2126
keyStore = AccessController.doPrivileged(action, context);
2127
return keyStore;
2128
} catch (PrivilegedActionException e) {
2129
oldException = e.getCause();
2130
throw new KeyStoreException
2131
("KeyStore instantiation failed", oldException);
2132
}
2133
}
2134
2135
public synchronized ProtectionParameter
2136
getProtectionParameter(String alias) {
2137
if (alias == null) {
2138
throw new NullPointerException();
2139
}
2140
if (keyStore == null) {
2141
throw new IllegalStateException
2142
("getKeyStore() must be called first");
2143
}
2144
return keyProtection;
2145
}
2146
}
2147
2148
/**
2149
* Returns a new Builder object.
2150
*
2151
* <p>Each call to the {@link #getKeyStore} method on the returned
2152
* builder will return a new KeyStore object of type {@code type}.
2153
* Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()}
2154
* method is invoked using a
2155
* {@code LoadStoreParameter} that encapsulates
2156
* {@code protection}.
2157
*
2158
* <p>The KeyStore is instantiated from {@code provider} if
2159
* non-null. Otherwise, all installed providers are searched.
2160
*
2161
* <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
2162
* will return {@code protection}.
2163
*
2164
* <p><em>Note</em> that the {@link #getKeyStore} method is executed
2165
* within the {@link AccessControlContext} of the code invoking this
2166
* method.
2167
*
2168
* @return a new Builder object
2169
* @param type the type of KeyStore to be constructed
2170
* @param provider the provider from which the KeyStore is to
2171
* be instantiated (or null)
2172
* @param protection the ProtectionParameter securing the Keystore
2173
* @throws NullPointerException if type or protection is null
2174
*/
2175
public static Builder newInstance(final String type,
2176
final Provider provider, final ProtectionParameter protection) {
2177
if ((type == null) || (protection == null)) {
2178
throw new NullPointerException();
2179
}
2180
@SuppressWarnings("removal")
2181
final AccessControlContext context = AccessController.getContext();
2182
return new Builder() {
2183
private volatile boolean getCalled;
2184
private IOException oldException;
2185
2186
private final PrivilegedExceptionAction<KeyStore> action
2187
= new PrivilegedExceptionAction<KeyStore>() {
2188
2189
public KeyStore run() throws Exception {
2190
KeyStore ks;
2191
if (provider == null) {
2192
ks = KeyStore.getInstance(type);
2193
} else {
2194
ks = KeyStore.getInstance(type, provider);
2195
}
2196
LoadStoreParameter param = new SimpleLoadStoreParameter(protection);
2197
if (!(protection instanceof CallbackHandlerProtection)) {
2198
ks.load(param);
2199
} else {
2200
// when using a CallbackHandler,
2201
// reprompt if the password is wrong
2202
int tries = 0;
2203
while (true) {
2204
tries++;
2205
try {
2206
ks.load(param);
2207
break;
2208
} catch (IOException e) {
2209
if (e.getCause() instanceof UnrecoverableKeyException) {
2210
if (tries < MAX_CALLBACK_TRIES) {
2211
continue;
2212
} else {
2213
oldException = e;
2214
}
2215
}
2216
throw e;
2217
}
2218
}
2219
}
2220
getCalled = true;
2221
return ks;
2222
}
2223
};
2224
2225
@SuppressWarnings("removal")
2226
public synchronized KeyStore getKeyStore()
2227
throws KeyStoreException {
2228
if (oldException != null) {
2229
throw new KeyStoreException
2230
("Previous KeyStore instantiation failed",
2231
oldException);
2232
}
2233
try {
2234
return AccessController.doPrivileged(action, context);
2235
} catch (PrivilegedActionException e) {
2236
Throwable cause = e.getCause();
2237
throw new KeyStoreException
2238
("KeyStore instantiation failed", cause);
2239
}
2240
}
2241
2242
public ProtectionParameter getProtectionParameter(String alias)
2243
{
2244
if (alias == null) {
2245
throw new NullPointerException();
2246
}
2247
if (getCalled == false) {
2248
throw new IllegalStateException
2249
("getKeyStore() must be called first");
2250
}
2251
return protection;
2252
}
2253
};
2254
}
2255
2256
}
2257
2258
static class SimpleLoadStoreParameter implements LoadStoreParameter {
2259
2260
private final ProtectionParameter protection;
2261
2262
SimpleLoadStoreParameter(ProtectionParameter protection) {
2263
this.protection = protection;
2264
}
2265
2266
public ProtectionParameter getProtectionParameter() {
2267
return protection;
2268
}
2269
}
2270
}
2271
2272