* The certificates of the chain are not added as trusted certificates, as only a * trusted certificate entry is a trust anchor. Use {@link #addTrustedCertificate} for * the issuers which have to be trusted. * * @param alias The alias to store the key entry under in this key store. It * must not be {@code null} or empty. * @param sourceManager The certificate manager of the key store holding the key entry * to copy. It must not be {@code null}. * @param sourceAlias The alias of the key entry to copy. It must not be * {@code null} or empty. * * @throws KeyStoreException If the source key store holds no key entry under the * provided alias, if its private key is protected by a * password other than the one of the source key store, if * the alias is already in use in this key store, or a * problem occurs while interacting with either key store. */ public void importKeyEntry(String alias, CertificateManager sourceManager, String sourceAlias) throws KeyStoreException { ensureValid(alias, CERT_ALIAS_MSG); ensureValid(sourceAlias, CERT_ALIAS_MSG); if (sourceManager == null) { LocalizableMessage msg = ERR_CERTMGR_VALUE_INVALID.get(SOURCE_KEYSTORE_MSG); throw new NullPointerException(msg.toString()); } final Certificate[] chain = sourceManager.getCertificateChain(sourceAlias); final Key privateKey; try { privateKey = sourceManager.getKeyStore().getKey(sourceAlias, sourceManager.password); } catch (UnrecoverableKeyException e) { // The key is protected by a password of its own. The key managers of the server // unlock private keys with the store password only, so this is the same limitation // the key store already has for LDAPS: say so rather than "Cannot recover key". throw new KeyStoreException( ERR_CERTMGR_KEY_PASSWORD_DIFFERS.get(sourceAlias, sourceManager.keyStorePath).toString(), e); } catch (GeneralSecurityException e) { throw new KeyStoreException( ERR_CERTMGR_IMPORT_KEY_ENTRY.get(sourceAlias, e.getMessage()).toString(), e); } if (privateKey == null || chain == null || chain.length == 0) { LocalizableMessage msg = ERR_CERTMGR_NO_KEY_ENTRY.get(sourceAlias, sourceManager.keyStorePath); throw new KeyStoreException(msg.toString()); } keyStore = null; Platform.importKeyEntry(getKeyStore(), keyStoreType, keyStorePath, alias, password, privateKey, chain); } /** * Adds the provided certificate to the key store as a trusted certificate entry. Only * such an entry is a trust anchor: of a key entry, the trust managers take the * certificate the key belongs to and none of its issuers. * * @param alias The alias to use for the certificate. It must not be * {@code null} or empty. * @param certificate The certificate to trust. It must not be {@code null}. * * @throws KeyStoreException If the alias is already in use, or a problem occurs while * interacting with the key store. */ public void addTrustedCertificate(String alias, Certificate certificate) throws KeyStoreException { ensureValid(alias, CERT_ALIAS_MSG); if (certificate == null) { LocalizableMessage msg = ERR_CERTMGR_VALUE_INVALID.get(CERT_MSG); throw new NullPointerException(msg.toString()); } keyStore = null; Platform.addTrustedCertificate(getKeyStore(), keyStoreType, keyStorePath, alias, password, certificate); } /** * Generates a self-signed certificate using the provided information. * * @param keyType Specifies the key size, key and signature algorithms. * @param alias The nickname to use for the certificate in the key * store. For the server certificate, it should generally * be "server-cert". It must not be {@code null} or empty. * @param subjectDN The subject DN to use for the certificate. It must not * be {@code null} or empty. * @param validity The length of time in days that the certificate should * be valid, starting from the time the certificate is * generated. It must be a positive integer value. * @throws KeyStoreException If a problem occurs while actually attempting * to generate the certificate in the key store. *@throws IllegalArgumentException If the validity parameter is not a * positive integer, or the alias is already * in the keystore. */ public void generateSelfSignedCertificate(KeyType keyType, String alias, String subjectDN, int validity) throws KeyStoreException, IllegalArgumentException { ensureValid(alias, CERT_ALIAS_MSG); ensureValid(subjectDN, SUBJECT_DN_MSG); if (validity <= 0) { LocalizableMessage msg = ERR_CERTMGR_VALIDITY.get(validity); throw new IllegalArgumentException(msg.toString()); } if (aliasInUse(alias)) { LocalizableMessage msg = ERR_CERTMGR_ALIAS_ALREADY_EXISTS.get(alias); throw new IllegalArgumentException(msg.toString()); } keyStore = null; Platform.generateSelfSignedCertificate(getKeyStore(), keyStoreType, keyStorePath, keyType, alias, password, subjectDN, validity); } /** * Adds the provided certificate to the key store. This may be used to * associate an externally-signed certificate with an existing private key * with the given alias. * * @param alias The alias to use for the certificate. It must not * be {@code null} or empty. * @param certificateFile The file containing the encoded certificate. It * must not be {@code null}, and the file must exist. * @throws KeyStoreException If a problem occurs while interacting with the * key store. * *@throws IllegalArgumentException If the certificate file is not valid. */ public void addCertificate(String alias, File certificateFile) throws KeyStoreException, IllegalArgumentException { ensureValid(alias, CERT_ALIAS_MSG); ensureFileValid(certificateFile, CERT_REQUEST_FILE_MSG); if (!certificateFile.exists() || !certificateFile.isFile()) { LocalizableMessage msg = ERR_CERTMGR_INVALID_CERT_FILE.get( certificateFile.getAbsolutePath()); throw new IllegalArgumentException(msg.toString()); } keyStore = null; Platform.addCertificate(getKeyStore(), keyStoreType, keyStorePath, alias, password, certificateFile.getAbsolutePath()); } /** * Removes the specified certificate from the key store. * * @param alias The alias to use for the certificate to remove. It must not * be {@code null} or an empty string, and it must exist in * the key store. * * @throws KeyStoreException If a problem occurs while interacting with the * key store. *@throws IllegalArgumentException If the alias is in use and cannot be * deleted. */ public void removeCertificate(String alias) throws KeyStoreException, IllegalArgumentException { ensureValid(alias, CERT_ALIAS_MSG); if (!aliasInUse(alias)) { LocalizableMessage msg = ERR_CERTMGR_ALIAS_CAN_NOT_DELETE.get(alias); throw new IllegalArgumentException(msg.toString()); } keyStore = null; Platform.deleteAlias(getKeyStore(), keyStorePath, alias, password); } /** * Retrieves a handle to the key store. * * @return The handle to the key store, or {@code null} if the key store * doesn't exist. * * @throws KeyStoreException If a problem occurs while trying to open the * key store. */ private KeyStore getKeyStore() throws KeyStoreException { if (keyStore != null) { return keyStore; } // For JKS and PKCS12 key stores, we should make sure the file exists, and // we'll need an input stream that we can use to read it. For PKCS11 key // stores there won't be a file and the input stream should be null. FileInputStream keyStoreInputStream = null; if (keyStoreType.equals(KEY_STORE_TYPE_JKS) || keyStoreType.equals(KEY_STORE_TYPE_JCEKS) || keyStoreType.equals(KEY_STORE_TYPE_PKCS12) || keyStoreType.equals(KEY_STORE_TYPE_BCFKS)) { final File keyStoreFile = new File(keyStorePath); if (! keyStoreFile.exists()) { return null; } try { keyStoreInputStream = new FileInputStream(keyStoreFile); } catch (final Exception e) { throw new KeyStoreException(String.valueOf(e), e); } } final KeyStore keyStore = KeyStore.getInstance(keyStoreType); try { keyStore.load(keyStoreInputStream, password); return this.keyStore = keyStore; } catch (final Exception e) { throw new KeyStoreException(String.valueOf(e), e); } finally { if (keyStoreInputStream != null) { try { keyStoreInputStream.close(); } catch (final Throwable t) { } } } } /** * Returns whether this certificate manager contains 'real' aliases or not. * For instance, the certificate manager can contain a PKCS12 certificate * with no alias. * @return whether this certificate manager contains 'real' aliases or not. * @throws KeyStoreException if there is a problem accessing the key store. */ public boolean hasRealAliases() throws KeyStoreException { if (realAliases == null) { String[] aliases = getCertificateAliases(); if (aliases == null || aliases.length == 0) { realAliases = Boolean.FALSE; } else if (aliases.length > 1) { realAliases = Boolean.TRUE; } else { CertificateManager certManager2 = new CertificateManager(keyStorePath, keyStoreType, password); String[] aliases2 = certManager2.getCertificateAliases(); if (aliases2 != null && aliases2.length == 1) { realAliases = aliases[0].equalsIgnoreCase(aliases2[0]); } else { realAliases = Boolean.FALSE; } } } return realAliases; } private static void ensureFileValid(File arg, String msgStr) { if(arg == null) { LocalizableMessage msg = ERR_CERTMGR_FILE_NAME_INVALID.get(msgStr); throw new NullPointerException(msg.toString()); } } private static void ensureValid(String arg, String msgStr) { if(arg == null || arg.length() == 0) { LocalizableMessage msg = ERR_CERTMGR_VALUE_INVALID.get(msgStr); throw new NullPointerException(msg.toString()); } } }