1 7 8 package java.security; 9 10 import java.io.*; 11 import java.security.cert.Certificate ; 12 import java.security.cert.X509Certificate ; 13 import java.security.cert.CertificateException ; 14 import java.util.*; 15 import javax.crypto.SecretKey; 16 17 import javax.security.auth.callback.*; 18 19 141 142 public class KeyStore { 143 144 152 private static final String KEYSTORE_TYPE = "keystore.type"; 153 154 private String type; 156 157 private Provider provider; 159 160 private KeyStoreSpi keyStoreSpi; 162 163 private boolean initialized = false; 165 166 175 public static interface LoadStoreParameter { 176 181 public ProtectionParameter getProtectionParameter(); 182 } 183 184 196 public static interface ProtectionParameter { } 197 198 203 public static class PasswordProtection implements 204 ProtectionParameter, javax.security.auth.Destroyable { 205 206 private final char[] password; 207 private volatile boolean destroyed = false; 208 209 217 public PasswordProtection(char[] password) { 218 this.password = (password == null) ? 219 null : (char[])password.clone(); 220 } 221 222 235 public synchronized char[] getPassword() { 236 if (destroyed) { 237 throw new IllegalStateException ("password has been cleared"); 238 } 239 return password; 240 } 241 242 248 public synchronized void destroy() 249 throws javax.security.auth.DestroyFailedException { 250 destroyed = true; 251 if (password != null) { 252 Arrays.fill(password, ' '); 253 } 254 } 255 256 261 public synchronized boolean isDestroyed() { 262 return destroyed; 263 } 264 } 265 266 271 public static class CallbackHandlerProtection 272 implements ProtectionParameter { 273 274 private final CallbackHandler handler; 275 276 283 public CallbackHandlerProtection(CallbackHandler handler) { 284 if (handler == null) { 285 throw new NullPointerException ("handler must not be null"); 286 } 287 this.handler = handler; 288 } 289 290 295 public CallbackHandler getCallbackHandler() { 296 return handler; 297 } 298 299 } 300 301 306 public static interface Entry { } 307 308 314 public static final class PrivateKeyEntry implements Entry { 315 316 private final PrivateKey privKey; 317 private final Certificate [] chain; 318 319 343 public PrivateKeyEntry(PrivateKey privateKey, Certificate [] chain) { 344 if (privateKey == null || chain == null) { 345 throw new NullPointerException ("invalid null input"); 346 } 347 if (chain.length == 0) { 348 throw new IllegalArgumentException 349 ("invalid zero-length input chain"); 350 } 351 352 Certificate [] clonedChain = (Certificate [])chain.clone(); 353 String certType = clonedChain[0].getType(); 354 for (int i = 1; i < clonedChain.length; i++) { 355 if (!certType.equals(clonedChain[i].getType())) { 356 throw new IllegalArgumentException 357 ("chain does not contain certificates " + 358 "of the same type"); 359 } 360 } 361 if (!privateKey.getAlgorithm().equals 362 (clonedChain[0].getPublicKey().getAlgorithm())) { 363 throw new IllegalArgumentException 364 ("private key algorithm does not match " + 365 "algorithm of public key in end entity " + 366 "certificate (at index 0)"); 367 } 368 this.privKey = privateKey; 369 370 if (clonedChain[0] instanceof X509Certificate && 371 !(clonedChain instanceof X509Certificate [])) { 372 373 this.chain = new X509Certificate [clonedChain.length]; 374 System.arraycopy(clonedChain, 0, 375 this.chain, 0, clonedChain.length); 376 } else { 377 this.chain = clonedChain; 378 } 379 } 380 381 386 public PrivateKey getPrivateKey() { 387 return privKey; 388 } 389 390 401 public Certificate [] getCertificateChain() { 402 return (Certificate [])chain.clone(); 403 } 404 405 415 public Certificate getCertificate() { 416 return chain[0]; 417 } 418 419 423 public String toString() { 424 StringBuilder sb = new StringBuilder (); 425 sb.append("Private key entry and certificate chain with " 426 + chain.length + " elements:\r\n"); 427 for (Certificate cert : chain) { 428 sb.append(cert); 429 sb.append("\r\n"); 430 } 431 return sb.toString(); 432 } 433 434 } 435 436 441 public static final class SecretKeyEntry implements Entry { 442 443 private final SecretKey sKey; 444 445 454 public SecretKeyEntry(SecretKey secretKey) { 455 if (secretKey == null) { 456 throw new NullPointerException ("invalid null input"); 457 } 458 this.sKey = secretKey; 459 } 460 461 466 public SecretKey getSecretKey() { 467 return sKey; 468 } 469 470 474 public String toString() { 475 return "Secret key entry with algorithm " + sKey.getAlgorithm(); 476 } 477 } 478 479 485 public static final class TrustedCertificateEntry implements Entry { 486 487 private final Certificate cert; 488 489 498 public TrustedCertificateEntry(Certificate trustedCert) { 499 if (trustedCert == null) { 500 throw new NullPointerException ("invalid null input"); 501 } 502 this.cert = trustedCert; 503 } 504 505 510 public Certificate getTrustedCertificate() { 511 return cert; 512 } 513 514 518 public String toString() { 519 return "Trusted certificate entry:\r\n" + cert.toString(); 520 } 521 } 522 523 531 protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type) 532 { 533 this.keyStoreSpi = keyStoreSpi; 534 this.provider = provider; 535 this.type = type; 536 } 537 538 558 public static KeyStore getInstance(String type) 559 throws KeyStoreException 560 { 561 try { 562 Object [] objs = Security.getImpl(type, "KeyStore", (String )null); 563 return new KeyStore ((KeyStoreSpi )objs[0], (Provider )objs[1], type); 564 } catch (NoSuchAlgorithmException nsae) { 565 throw new KeyStoreException (type + " not found"); 566 } catch (NoSuchProviderException nspe) { 567 throw new KeyStoreException (type + " not found"); 568 } 569 } 570 571 597 public static KeyStore getInstance(String type, String provider) 598 throws KeyStoreException , NoSuchProviderException 599 { 600 if (provider == null || provider.length() == 0) 601 throw new IllegalArgumentException ("missing provider"); 602 try { 603 Object [] objs = Security.getImpl(type, "KeyStore", provider); 604 return new KeyStore ((KeyStoreSpi )objs[0], (Provider )objs[1], type); 605 } catch (NoSuchAlgorithmException nsae) { 606 throw new KeyStoreException (type + " not found"); 607 } 608 } 609 610 636 public static KeyStore getInstance(String type, Provider provider) 637 throws KeyStoreException 638 { 639 if (provider == null) 640 throw new IllegalArgumentException ("missing provider"); 641 try { 642 Object [] objs = Security.getImpl(type, "KeyStore", provider); 643 return new KeyStore ((KeyStoreSpi )objs[0], (Provider )objs[1], type); 644 } catch (NoSuchAlgorithmException nsae) { 645 throw new KeyStoreException (type + " not found"); 646 } 647 } 648 649 671 public final static String getDefaultType() { 672 String kstype; 673 kstype = (String )AccessController.doPrivileged(new PrivilegedAction () { 674 public Object run() { 675 return Security.getProperty(KEYSTORE_TYPE); 676 } 677 }); 678 if (kstype == null) { 679 kstype = "jks"; 680 } 681 return kstype; 682 } 683 684 689 public final Provider getProvider() 690 { 691 return this.provider; 692 } 693 694 699 public final String getType() 700 { 701 return this.type; 702 } 703 704 724 public final Key getKey(String alias, char[] password) 725 throws KeyStoreException , NoSuchAlgorithmException , 726 UnrecoverableKeyException 727 { 728 if (!initialized) { 729 throw new KeyStoreException ("Uninitialized keystore"); 730 } 731 return keyStoreSpi.engineGetKey(alias, password); 732 } 733 734 750 public final Certificate [] getCertificateChain(String alias) 751 throws KeyStoreException 752 { 753 if (!initialized) { 754 throw new KeyStoreException ("Uninitialized keystore"); 755 } 756 return keyStoreSpi.engineGetCertificateChain(alias); 757 } 758 759 783 public final Certificate getCertificate(String alias) 784 throws KeyStoreException 785 { 786 if (!initialized) { 787 throw new KeyStoreException ("Uninitialized keystore"); 788 } 789 return keyStoreSpi.engineGetCertificate(alias); 790 } 791 792 803 public final Date getCreationDate(String alias) 804 throws KeyStoreException 805 { 806 if (!initialized) { 807 throw new KeyStoreException ("Uninitialized keystore"); 808 } 809 return keyStoreSpi.engineGetCreationDate(alias); 810 } 811 812 835 public final void setKeyEntry(String alias, Key key, char[] password, 836 Certificate [] chain) 837 throws KeyStoreException 838 { 839 if (!initialized) { 840 throw new KeyStoreException ("Uninitialized keystore"); 841 } 842 if ((key instanceof PrivateKey ) && 843 (chain == null || chain.length == 0)) { 844 throw new IllegalArgumentException ("Private key must be " 845 + "accompanied by certificate " 846 + "chain"); 847 } 848 keyStoreSpi.engineSetKeyEntry(alias, key, password, chain); 849 } 850 851 875 public final void setKeyEntry(String alias, byte[] key, 876 Certificate [] chain) 877 throws KeyStoreException 878 { 879 if (!initialized) { 880 throw new KeyStoreException ("Uninitialized keystore"); 881 } 882 keyStoreSpi.engineSetKeyEntry(alias, key, chain); 883 } 884 885 903 public final void setCertificateEntry(String alias, Certificate cert) 904 throws KeyStoreException 905 { 906 if (!initialized) { 907 throw new KeyStoreException ("Uninitialized keystore"); 908 } 909 keyStoreSpi.engineSetCertificateEntry(alias, cert); 910 } 911 912 920 public final void deleteEntry(String alias) 921 throws KeyStoreException 922 { 923 if (!initialized) { 924 throw new KeyStoreException ("Uninitialized keystore"); 925 } 926 keyStoreSpi.engineDeleteEntry(alias); 927 } 928 929 937 public final Enumeration<String > aliases() 938 throws KeyStoreException 939 { 940 if (!initialized) { 941 throw new KeyStoreException ("Uninitialized keystore"); 942 } 943 return keyStoreSpi.engineAliases(); 944 } 945 946 956 public final boolean containsAlias(String alias) 957 throws KeyStoreException 958 { 959 if (!initialized) { 960 throw new KeyStoreException ("Uninitialized keystore"); 961 } 962 return keyStoreSpi.engineContainsAlias(alias); 963 } 964 965 973 public final int size() 974 throws KeyStoreException 975 { 976 if (!initialized) { 977 throw new KeyStoreException ("Uninitialized keystore"); 978 } 979 return keyStoreSpi.engineSize(); 980 } 981 982 996 public final boolean isKeyEntry(String alias) 997 throws KeyStoreException 998 { 999 if (!initialized) { 1000 throw new KeyStoreException ("Uninitialized keystore"); 1001 } 1002 return keyStoreSpi.engineIsKeyEntry(alias); 1003 } 1004 1005 1019 public final boolean isCertificateEntry(String alias) 1020 throws KeyStoreException 1021 { 1022 if (!initialized) { 1023 throw new KeyStoreException ("Uninitialized keystore"); 1024 } 1025 return keyStoreSpi.engineIsCertificateEntry(alias); 1026 } 1027 1028 1054 public final String getCertificateAlias(Certificate cert) 1055 throws KeyStoreException 1056 { 1057 if (!initialized) { 1058 throw new KeyStoreException ("Uninitialized keystore"); 1059 } 1060 return keyStoreSpi.engineGetCertificateAlias(cert); 1061 } 1062 1063 1078 public final void store(OutputStream stream, char[] password) 1079 throws KeyStoreException , IOException, NoSuchAlgorithmException , 1080 CertificateException 1081 { 1082 if (!initialized) { 1083 throw new KeyStoreException ("Uninitialized keystore"); 1084 } 1085 keyStoreSpi.engineStore(stream, password); 1086 } 1087 1088 1108 public final void store(LoadStoreParameter param) 1109 throws KeyStoreException , IOException, 1110 NoSuchAlgorithmException , CertificateException { 1111 if (!initialized) { 1112 throw new KeyStoreException ("Uninitialized keystore"); 1113 } 1114 keyStoreSpi.engineStore(param); 1115 } 1116 1117 1147 public final void load(InputStream stream, char[] password) 1148 throws IOException, NoSuchAlgorithmException , CertificateException 1149 { 1150 keyStoreSpi.engineLoad(stream, password); 1151 initialized = true; 1152 } 1153 1154 1176 public final void load(LoadStoreParameter param) 1177 throws IOException, NoSuchAlgorithmException , 1178 CertificateException { 1179 1180 keyStoreSpi.engineLoad(param); 1181 initialized = true; 1182 } 1183 1184 1208 public final Entry getEntry(String alias, ProtectionParameter protParam) 1209 throws NoSuchAlgorithmException , UnrecoverableEntryException , 1210 KeyStoreException { 1211 1212 if (alias == null) { 1213 throw new NullPointerException ("invalid null input"); 1214 } 1215 if (!initialized) { 1216 throw new KeyStoreException ("Uninitialized keystore"); 1217 } 1218 return keyStoreSpi.engineGetEntry(alias, protParam); 1219 } 1220 1221 1245 public final void setEntry(String alias, Entry entry, 1246 ProtectionParameter protParam) 1247 throws KeyStoreException { 1248 if (alias == null || entry == null) { 1249 throw new NullPointerException ("invalid null input"); 1250 } 1251 if (!initialized) { 1252 throw new KeyStoreException ("Uninitialized keystore"); 1253 } 1254 keyStoreSpi.engineSetEntry(alias, entry, protParam); 1255 } 1256 1257 1277 public final boolean 1278 entryInstanceOf(String alias, 1279 Class <? extends KeyStore.Entry > entryClass) 1280 throws KeyStoreException 1281 { 1282 1283 if (alias == null || entryClass == null) { 1284 throw new NullPointerException ("invalid null input"); 1285 } 1286 if (!initialized) { 1287 throw new KeyStoreException ("Uninitialized keystore"); 1288 } 1289 return keyStoreSpi.engineEntryInstanceOf(alias, entryClass); 1290 } 1291 1292 1307 public static abstract class Builder { 1308 1309 1312 protected Builder() { 1313 } 1315 1316 1323 public abstract KeyStore getKeyStore() throws KeyStoreException ; 1324 1325 1340 public abstract ProtectionParameter getProtectionParameter(String alias) 1341 throws KeyStoreException ; 1342 1343 1362 public static Builder newInstance(final KeyStore keyStore, 1363 final ProtectionParameter protectionParameter) { 1364 if ((keyStore == null) || (protectionParameter == null)) { 1365 throw new NullPointerException (); 1366 } 1367 if (keyStore.initialized == false) { 1368 throw new IllegalArgumentException ("KeyStore not initialized"); 1369 } 1370 return new Builder() { 1371 private volatile boolean getCalled; 1372 1373 public KeyStore getKeyStore() { 1374 getCalled = true; 1375 return keyStore; 1376 } 1377 1378 public ProtectionParameter getProtectionParameter(String alias) 1379 { 1380 if (alias == null) { 1381 throw new NullPointerException (); 1382 } 1383 if (getCalled == false) { 1384 throw new IllegalStateException 1385 ("getKeyStore() must be called first"); 1386 } 1387 return protectionParameter; 1388 } 1389 }; 1390 } 1391 1392 1435 public static Builder newInstance(String type, Provider provider, 1436 File file, ProtectionParameter protection) { 1437 if ((type == null) || (file == null) || (protection == null)) { 1438 throw new NullPointerException (); 1439 } 1440 if ((protection instanceof PasswordProtection == false) && 1441 (protection instanceof CallbackHandlerProtection == false)) { 1442 throw new IllegalArgumentException 1443 ("Protection must be PasswordProtection or " + 1444 "CallbackHandlerProtection"); 1445 } 1446 if (file.isFile() == false) { 1447 throw new IllegalArgumentException 1448 ("File does not exist or it does not refer " + 1449 "to a normal file: " + file); 1450 } 1451 return new FileBuilder(type, provider, file, protection, 1452 AccessController.getContext()); 1453 } 1454 1455 private static final class FileBuilder extends Builder { 1456 1457 private final String type; 1458 private final Provider provider; 1459 private final File file; 1460 private ProtectionParameter protection; 1461 private final AccessControlContext context; 1462 1463 private KeyStore keyStore; 1464 1465 private Throwable oldException; 1466 1467 FileBuilder(String type, Provider provider, File file, 1468 ProtectionParameter protection, 1469 AccessControlContext context) { 1470 this.type = type; 1471 this.provider = provider; 1472 this.file = file; 1473 this.protection = protection; 1474 this.context = context; 1475 } 1476 1477 public synchronized KeyStore getKeyStore() throws KeyStoreException 1478 { 1479 if (keyStore != null) { 1480 return keyStore; 1481 } 1482 if (oldException != null) { 1483 throw new KeyStoreException 1484 ("Previous KeyStore instantiation failed", 1485 oldException); 1486 } 1487 PrivilegedExceptionAction action = 1488 new PrivilegedExceptionAction () { 1489 public Object run() throws Exception { 1490 KeyStore ks; 1491 if (provider == null) { 1492 ks = KeyStore.getInstance(type); 1493 } else { 1494 ks = KeyStore.getInstance(type, provider); 1495 } 1496 InputStream in = null; 1497 char[] password = null; 1498 try { 1499 in = new FileInputStream(file); 1500 if (protection instanceof PasswordProtection) { 1501 password = 1502 ((PasswordProtection)protection).getPassword(); 1503 } else { 1504 CallbackHandler handler = 1505 ((CallbackHandlerProtection)protection) 1506 .getCallbackHandler(); 1507 PasswordCallback callback = new PasswordCallback 1508 ("Password for keystore " + file.getName(), 1509 false); 1510 handler.handle(new Callback[] {callback}); 1511 password = callback.getPassword(); 1512 if (password == null) { 1513 throw new KeyStoreException ("No password" + 1514 " provided"); 1515 } 1516 callback.clearPassword(); 1517 protection = new PasswordProtection(password); 1518 } 1519 ks.load(in, password); 1520 return ks; 1521 } finally { 1522 if (in != null) { 1523 in.close(); 1524 } 1525 } 1526 } 1527 }; 1528 try { 1529 keyStore = (KeyStore )AccessController.doPrivileged 1530 (action, context); 1531 return keyStore; 1532 } catch (PrivilegedActionException e) { 1533 oldException = e.getCause(); 1534 throw new KeyStoreException 1535 ("KeyStore instantiation failed", oldException); 1536 } 1537 } 1538 1539 public synchronized ProtectionParameter 1540 getProtectionParameter(String alias) { 1541 if (alias == null) { 1542 throw new NullPointerException (); 1543 } 1544 if (keyStore == null) { 1545 throw new IllegalStateException 1546 ("getKeyStore() must be called first"); 1547 } 1548 return protection; 1549 } 1550 } 1551 1552 1579 public static Builder newInstance(final String type, 1580 final Provider provider, final ProtectionParameter protection) { 1581 if ((type == null) || (protection == null)) { 1582 throw new NullPointerException (); 1583 } 1584 final AccessControlContext context = AccessController.getContext(); 1585 return new Builder() { 1586 private volatile boolean getCalled; 1587 1588 private final PrivilegedExceptionAction action 1589 = new PrivilegedExceptionAction () { 1590 1591 public Object run() throws Exception { 1592 KeyStore ks; 1593 if (provider == null) { 1594 ks = KeyStore.getInstance(type); 1595 } else { 1596 ks = KeyStore.getInstance(type, provider); 1597 } 1598 ks.load(new SimpleLoadStoreParameter(protection)); 1599 getCalled = true; 1600 return ks; 1601 } 1602 }; 1603 1604 public synchronized KeyStore getKeyStore() 1605 throws KeyStoreException { 1606 try { 1607 return (KeyStore )AccessController.doPrivileged(action); 1608 } catch (PrivilegedActionException e) { 1609 Throwable cause = e.getCause(); 1610 throw new KeyStoreException 1611 ("KeyStore instantiation failed", cause); 1612 } 1613 } 1614 1615 public ProtectionParameter getProtectionParameter(String alias) 1616 { 1617 if (alias == null) { 1618 throw new NullPointerException (); 1619 } 1620 if (getCalled == false) { 1621 throw new IllegalStateException 1622 ("getKeyStore() must be called first"); 1623 } 1624 return protection; 1625 } 1626 }; 1627 } 1628 1629 } 1630 1631 static class SimpleLoadStoreParameter implements LoadStoreParameter { 1632 1633 private final ProtectionParameter protection; 1634 1635 SimpleLoadStoreParameter(ProtectionParameter protection) { 1636 this.protection = protection; 1637 } 1638 1639 public ProtectionParameter getProtectionParameter() { 1640 return protection; 1641 } 1642 } 1643 1644} 1645 1646 | Popular Tags |