90 * secret) keys. Smart cards or other integrated cryptographic engines |
90 * secret) keys. Smart cards or other integrated cryptographic engines |
91 * (SafeKeyper) are one option, and simpler mechanisms such as files may also |
91 * (SafeKeyper) are one option, and simpler mechanisms such as files may also |
92 * be used (in a variety of formats). |
92 * be used (in a variety of formats). |
93 * |
93 * |
94 * <p> Typical ways to request a KeyStore object include |
94 * <p> Typical ways to request a KeyStore object include |
|
95 * specifying an existing keystore file, |
95 * relying on the default type and providing a specific keystore type. |
96 * relying on the default type and providing a specific keystore type. |
96 * |
97 * |
97 * <ul> |
98 * <ul> |
|
99 * <li>To specify an existing keystore file: |
|
100 * <pre> |
|
101 * // get keystore password |
|
102 * char[] password = getPassword(); |
|
103 * |
|
104 * // probe the keystore file and load the keystore entries |
|
105 * KeyStore ks = KeyStore.getInstance(new File("keyStoreName"), password); |
|
106 *</pre> |
|
107 * The system will probe the specified file to determine its keystore type |
|
108 * and return a keystore implementation with its entries already loaded. |
|
109 * When this approach is used there is no need to call the keystore's |
|
110 * {@link #load(java.io.InputStream, char[]) load} method. |
|
111 * |
98 * <li>To rely on the default type: |
112 * <li>To rely on the default type: |
99 * <pre> |
113 * <pre> |
100 * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); |
114 * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); |
101 * </pre> |
115 * </pre> |
102 * The system will return a keystore implementation for the default type. |
116 * The system will return a keystore implementation for the default type. |
1592 } |
1608 } |
1593 return keyStoreSpi.engineEntryInstanceOf(alias, entryClass); |
1609 return keyStoreSpi.engineEntryInstanceOf(alias, entryClass); |
1594 } |
1610 } |
1595 |
1611 |
1596 /** |
1612 /** |
|
1613 * Returns a loaded keystore object of the appropriate keystore type. |
|
1614 * First the keystore type is determined by probing the specified file. |
|
1615 * Then a keystore object is instantiated and loaded using the data from |
|
1616 * that file. |
|
1617 * A password may be supplied to unlock the keystore data or perform an |
|
1618 * integrity check. |
|
1619 * |
|
1620 * <p> |
|
1621 * This method traverses the list of registered security {@link Providers}, |
|
1622 * starting with the most preferred Provider. |
|
1623 * For each {@link KeyStoreSpi} implementation supported by a Provider, |
|
1624 * it invokes the {@link engineProbe} method to determine if it supports |
|
1625 * the specified keystore. |
|
1626 * A new KeyStore object is returned that encapsulates the KeyStoreSpi |
|
1627 * implementation from the first Provider that supports the specified file. |
|
1628 * |
|
1629 * <p> Note that the list of registered providers may be retrieved via |
|
1630 * the {@link Security#getProviders() Security.getProviders()} method. |
|
1631 * |
|
1632 * @param file the keystore file |
|
1633 * @param password the keystore password, which may be {@code null} |
|
1634 * |
|
1635 * @return a keystore object loaded with keystore data |
|
1636 * |
|
1637 * @throws KeyStoreException if no Provider supports a KeyStoreSpi |
|
1638 * implementation for the specified keystore file. |
|
1639 * @throws IOException if there is an I/O or format problem with the |
|
1640 * keystore data, if a password is required but not given, |
|
1641 * or if the given password was incorrect. If the error is |
|
1642 * due to a wrong password, the {@link Throwable#getCause cause} |
|
1643 * of the {@code IOException} should be an |
|
1644 * {@code UnrecoverableKeyException}. |
|
1645 * @throws NoSuchAlgorithmException if the algorithm used to check the |
|
1646 * integrity of the keystore cannot be found. |
|
1647 * @throws CertificateException if any of the certificates in the |
|
1648 * keystore could not be loaded. |
|
1649 * @throws IllegalArgumentException if file does not exist or does not |
|
1650 * refer to a normal file. |
|
1651 * @throws NullPointerException if file is {@code null}. |
|
1652 * @throws SecurityException if a security manager exists and its |
|
1653 * {@link java.lang.SecurityManager#checkRead} method denies |
|
1654 * read access to the specified file. |
|
1655 * |
|
1656 * @see Provider |
|
1657 * |
|
1658 * @since 1.9 |
|
1659 */ |
|
1660 public static final KeyStore getInstance(File file, char[] password) |
|
1661 throws KeyStoreException, IOException, NoSuchAlgorithmException, |
|
1662 CertificateException { |
|
1663 return getInstance(file, password, null, true); |
|
1664 } |
|
1665 |
|
1666 /** |
|
1667 * Returns a loaded keystore object of the appropriate keystore type. |
|
1668 * First the keystore type is determined by probing the specified file. |
|
1669 * Then a keystore object is instantiated and loaded using the data from |
|
1670 * that file. |
|
1671 * A {@code LoadStoreParameter} may be supplied which specifies how to |
|
1672 * unlock the keystore data or perform an integrity check. |
|
1673 * |
|
1674 * <p> |
|
1675 * This method traverses the list of registered security {@link Providers}, |
|
1676 * starting with the most preferred Provider. |
|
1677 * For each {@link KeyStoreSpi} implementation supported by a Provider, |
|
1678 * it invokes the {@link engineProbe} method to determine if it supports |
|
1679 * the specified keystore. |
|
1680 * A new KeyStore object is returned that encapsulates the KeyStoreSpi |
|
1681 * implementation from the first Provider that supports the specified file. |
|
1682 * |
|
1683 * <p> Note that the list of registered providers may be retrieved via |
|
1684 * the {@link Security#getProviders() Security.getProviders()} method. |
|
1685 * |
|
1686 * @param file the keystore file |
|
1687 * @param param the {@code LoadStoreParameter} that specifies how to load |
|
1688 * the keystore, which may be {@code null} |
|
1689 * |
|
1690 * @return a keystore object loaded with keystore data |
|
1691 * |
|
1692 * @throws KeyStoreException if no Provider supports a KeyStoreSpi |
|
1693 * implementation for the specified keystore file. |
|
1694 * @throws IOException if there is an I/O or format problem with the |
|
1695 * keystore data. If the error is due to an incorrect |
|
1696 * {@code ProtectionParameter} (e.g. wrong password) |
|
1697 * the {@link Throwable#getCause cause} of the |
|
1698 * {@code IOException} should be an |
|
1699 * {@code UnrecoverableKeyException}. |
|
1700 * @throws NoSuchAlgorithmException if the algorithm used to check the |
|
1701 * integrity of the keystore cannot be found. |
|
1702 * @throws CertificateException if any of the certificates in the |
|
1703 * keystore could not be loaded. |
|
1704 * @throws IllegalArgumentException if file does not exist or does not |
|
1705 * refer to a normal file, or if param is not recognized. |
|
1706 * @throws NullPointerException if file is {@code null}. |
|
1707 * @throws SecurityException if a security manager exists and its |
|
1708 * {@link java.lang.SecurityManager#checkRead} method denies |
|
1709 * read access to the specified file. |
|
1710 * |
|
1711 * @see Provider |
|
1712 * |
|
1713 * @since 1.9 |
|
1714 */ |
|
1715 public static final KeyStore getInstance(File file, |
|
1716 LoadStoreParameter param) throws KeyStoreException, IOException, |
|
1717 NoSuchAlgorithmException, CertificateException { |
|
1718 return getInstance(file, null, param, false); |
|
1719 } |
|
1720 |
|
1721 // Used by getInstance(File, char[]) & getInstance(File, LoadStoreParameter) |
|
1722 private static final KeyStore getInstance(File file, char[] password, |
|
1723 LoadStoreParameter param, boolean hasPassword) |
|
1724 throws KeyStoreException, IOException, NoSuchAlgorithmException, |
|
1725 CertificateException { |
|
1726 |
|
1727 if (file == null) { |
|
1728 throw new NullPointerException(); |
|
1729 } |
|
1730 |
|
1731 if (file.isFile() == false) { |
|
1732 throw new IllegalArgumentException( |
|
1733 "File does not exist or it does not refer to a normal file: " + |
|
1734 file); |
|
1735 } |
|
1736 |
|
1737 KeyStore keystore = null; |
|
1738 |
|
1739 try (DataInputStream dataStream = |
|
1740 new DataInputStream( |
|
1741 new BufferedInputStream( |
|
1742 new FileInputStream(file)))) { |
|
1743 |
|
1744 dataStream.mark(Integer.MAX_VALUE); |
|
1745 |
|
1746 // Detect the keystore type |
|
1747 for (String type : Security.getAlgorithms("KeyStore")) { |
|
1748 Object[] objs = null; |
|
1749 |
|
1750 try { |
|
1751 objs = Security.getImpl(type, "KeyStore", (String)null); |
|
1752 |
|
1753 KeyStoreSpi impl = (KeyStoreSpi)objs[0]; |
|
1754 if (impl.engineProbe(dataStream)) { |
|
1755 |
|
1756 if (kdebug != null) { |
|
1757 kdebug.println(type + " keystore detected: " + |
|
1758 file); |
|
1759 } |
|
1760 |
|
1761 keystore = new KeyStore(impl, (Provider)objs[1], type); |
|
1762 break; |
|
1763 } |
|
1764 } catch (NoSuchAlgorithmException | NoSuchProviderException e) { |
|
1765 // ignore |
|
1766 if (kdebug != null) { |
|
1767 kdebug.println(type + " not found - " + e); |
|
1768 } |
|
1769 } catch (IOException e) { |
|
1770 // ignore |
|
1771 if (kdebug != null) { |
|
1772 kdebug.println("I/O error in " + file + " - " + e); |
|
1773 } |
|
1774 } |
|
1775 dataStream.reset(); // prepare the stream for the next probe |
|
1776 } |
|
1777 |
|
1778 // Load the keystore data |
|
1779 if (keystore != null) { |
|
1780 if (hasPassword) { |
|
1781 dataStream.reset(); // prepare the stream for loading |
|
1782 keystore.load(dataStream, password); |
|
1783 } else { |
|
1784 keystore.load(param); |
|
1785 } |
|
1786 return keystore; |
|
1787 } |
|
1788 } |
|
1789 |
|
1790 throw new KeyStoreException("Unrecognized keystore format: " + |
|
1791 keystore); |
|
1792 } |
|
1793 |
|
1794 /** |
1597 * A description of a to-be-instantiated KeyStore object. |
1795 * A description of a to-be-instantiated KeyStore object. |
1598 * |
1796 * |
1599 * <p>An instance of this class encapsulates the information needed to |
1797 * <p>An instance of this class encapsulates the information needed to |
1600 * instantiate and initialize a KeyStore object. That process is |
1798 * instantiate and initialize a KeyStore object. That process is |
1601 * triggered when the {@linkplain #getKeyStore} method is called. |
1799 * triggered when the {@linkplain #getKeyStore} method is called. |
1756 ("File does not exist or it does not refer " + |
1954 ("File does not exist or it does not refer " + |
1757 "to a normal file: " + file); |
1955 "to a normal file: " + file); |
1758 } |
1956 } |
1759 return new FileBuilder(type, provider, file, protection, |
1957 return new FileBuilder(type, provider, file, protection, |
1760 AccessController.getContext()); |
1958 AccessController.getContext()); |
|
1959 } |
|
1960 |
|
1961 /** |
|
1962 * Returns a new Builder object. |
|
1963 * |
|
1964 * <p>The first call to the {@link #getKeyStore} method on the returned |
|
1965 * builder will create a KeyStore using {@code file} to detect the |
|
1966 * keystore type and then call its {@link KeyStore#load load()} method. |
|
1967 * It uses the same algorithm to determine the keystore type as |
|
1968 * described in {@link KeyStore#getInstance(File, LoadStoreParameter)}. |
|
1969 * The {@code inputStream} argument is constructed from {@code file}. |
|
1970 * If {@code protection} is a {@code PasswordProtection}, the password |
|
1971 * is obtained by calling the {@code getPassword} method. |
|
1972 * Otherwise, if {@code protection} is a |
|
1973 * {@code CallbackHandlerProtection}, |
|
1974 * the password is obtained by invoking the CallbackHandler. |
|
1975 * |
|
1976 * <p>Subsequent calls to {@link #getKeyStore} return the same object |
|
1977 * as the initial call. If the initial call failed with a |
|
1978 * KeyStoreException, subsequent calls also throw a KeyStoreException. |
|
1979 * |
|
1980 * <p>Calls to {@link #getProtectionParameter getProtectionParameter()} |
|
1981 * will return a {@link KeyStore.PasswordProtection PasswordProtection} |
|
1982 * object encapsulating the password that was used to invoke the |
|
1983 * {@code load} method. |
|
1984 * |
|
1985 * <p><em>Note</em> that the {@link #getKeyStore} method is executed |
|
1986 * within the {@link AccessControlContext} of the code invoking this |
|
1987 * method. |
|
1988 * |
|
1989 * @return a new Builder object |
|
1990 * @param file the File that contains the KeyStore data |
|
1991 * @param protection the ProtectionParameter securing the KeyStore data |
|
1992 * @throws NullPointerException if file or protection is null |
|
1993 * @throws IllegalArgumentException if protection is not an instance |
|
1994 * of either PasswordProtection or CallbackHandlerProtection; or |
|
1995 * if file does not exist or does not refer to a normal file |
|
1996 * |
|
1997 * @since 1.9 |
|
1998 */ |
|
1999 public static Builder newInstance(File file, |
|
2000 ProtectionParameter protection) { |
|
2001 |
|
2002 return newInstance("", null, file, protection); |
1761 } |
2003 } |
1762 |
2004 |
1763 private static final class FileBuilder extends Builder { |
2005 private static final class FileBuilder extends Builder { |
1764 |
2006 |
1765 private final String type; |
2007 private final String type; |
1815 } |
2057 } |
1816 } |
2058 } |
1817 } |
2059 } |
1818 public KeyStore run0() throws Exception { |
2060 public KeyStore run0() throws Exception { |
1819 KeyStore ks; |
2061 KeyStore ks; |
1820 if (provider == null) { |
2062 char[] password = null; |
1821 ks = KeyStore.getInstance(type); |
2063 |
|
2064 // Acquire keystore password |
|
2065 if (protection instanceof PasswordProtection) { |
|
2066 password = |
|
2067 ((PasswordProtection)protection).getPassword(); |
|
2068 keyProtection = protection; |
1822 } else { |
2069 } else { |
1823 ks = KeyStore.getInstance(type, provider); |
2070 CallbackHandler handler = |
|
2071 ((CallbackHandlerProtection)protection) |
|
2072 .getCallbackHandler(); |
|
2073 PasswordCallback callback = new PasswordCallback |
|
2074 ("Password for keystore " + file.getName(), |
|
2075 false); |
|
2076 handler.handle(new Callback[] {callback}); |
|
2077 password = callback.getPassword(); |
|
2078 if (password == null) { |
|
2079 throw new KeyStoreException("No password" + |
|
2080 " provided"); |
|
2081 } |
|
2082 callback.clearPassword(); |
|
2083 keyProtection = new PasswordProtection(password); |
1824 } |
2084 } |
1825 InputStream in = null; |
2085 |
1826 char[] password = null; |
2086 if (type.isEmpty()) { |
1827 try { |
2087 // Instantiate keystore and load keystore data |
1828 in = new FileInputStream(file); |
2088 ks = KeyStore.getInstance(file, password); |
1829 if (protection instanceof PasswordProtection) { |
2089 } else { |
1830 password = |
2090 // Instantiate keystore |
1831 ((PasswordProtection)protection).getPassword(); |
2091 if (provider == null) { |
1832 keyProtection = protection; |
2092 ks = KeyStore.getInstance(type); |
1833 } else { |
2093 } else { |
1834 CallbackHandler handler = |
2094 ks = KeyStore.getInstance(type, provider); |
1835 ((CallbackHandlerProtection)protection) |
|
1836 .getCallbackHandler(); |
|
1837 PasswordCallback callback = new PasswordCallback |
|
1838 ("Password for keystore " + file.getName(), |
|
1839 false); |
|
1840 handler.handle(new Callback[] {callback}); |
|
1841 password = callback.getPassword(); |
|
1842 if (password == null) { |
|
1843 throw new KeyStoreException("No password" + |
|
1844 " provided"); |
|
1845 } |
|
1846 callback.clearPassword(); |
|
1847 keyProtection = new PasswordProtection(password); |
|
1848 } |
2095 } |
1849 ks.load(in, password); |
2096 // Load keystore data |
1850 return ks; |
2097 try (InputStream in = new FileInputStream(file)) { |
1851 } finally { |
2098 ks.load(in, password); |
1852 if (in != null) { |
|
1853 in.close(); |
|
1854 } |
2099 } |
1855 } |
2100 } |
|
2101 return ks; |
1856 } |
2102 } |
1857 }; |
2103 }; |
1858 try { |
2104 try { |
1859 keyStore = AccessController.doPrivileged(action, context); |
2105 keyStore = AccessController.doPrivileged(action, context); |
1860 return keyStore; |
2106 return keyStore; |