blob: 4def6e2f94c8ce2b43f32e911943fc2dfb4a19f1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.util;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class KeyStoreUtils {
private static final Logger logger = LoggerFactory.getLogger(KeyStoreUtils.class);
public static final String SUN_PROVIDER_NAME = "SUN";
public static final String SUN_JSSE_PROVIDER_NAME = "SunJSSE";
private static final String JKS_EXT = ".jks";
private static final String PKCS12_EXT = ".p12";
private static final String BCFKS_EXT = ".bcfks";
private static final String KEY_ALIAS = "nifi-key";
private static final String CERT_ALIAS = "nifi-cert";
private static final String CERT_DN = "CN=localhost";
private static final String KEY_ALGORITHM = "RSA";
private static final String SIGNING_ALGORITHM = "SHA256withRSA";
private static final int CERT_DURATION_DAYS = 365;
private static final int PASSWORD_LENGTH = 16;
private static final String TEST_KEYSTORE_PREFIX = "test-keystore-";
private static final String TEST_TRUSTSTORE_PREFIX = "test-truststore-";
private static final String KEYSTORE_ERROR_MSG = "There was an error creating a Keystore.";
private static final String TRUSTSTORE_ERROR_MSG = "There was an error creating a Truststore.";
private static final Map<String, String> KEY_STORE_TYPE_PROVIDERS = new HashMap<>();
private static final Map<KeystoreType, String> KEY_STORE_EXTENSIONS = new HashMap<>();
private static final Map<KeystoreType, String> SECRET_KEY_STORE_PROVIDERS = new HashMap<>();
static {
Security.addProvider(new BouncyCastleProvider());
KEY_STORE_TYPE_PROVIDERS.put(KeystoreType.BCFKS.getType(), BouncyCastleProvider.PROVIDER_NAME);
KEY_STORE_TYPE_PROVIDERS.put(KeystoreType.PKCS12.getType(), BouncyCastleProvider.PROVIDER_NAME);
KEY_STORE_TYPE_PROVIDERS.put(KeystoreType.JKS.getType(), SUN_PROVIDER_NAME);
SECRET_KEY_STORE_PROVIDERS.put(KeystoreType.BCFKS, BouncyCastleProvider.PROVIDER_NAME);
SECRET_KEY_STORE_PROVIDERS.put(KeystoreType.PKCS12, SUN_JSSE_PROVIDER_NAME);
}
static {
KEY_STORE_EXTENSIONS.put(KeystoreType.JKS, JKS_EXT);
KEY_STORE_EXTENSIONS.put(KeystoreType.PKCS12, PKCS12_EXT);
KEY_STORE_EXTENSIONS.put(KeystoreType.BCFKS, BCFKS_EXT);
}
/**
* Returns the provider that will be used for the given keyStoreType
*
* @param keyStoreType the keyStoreType
* @return Key Store Provider Name or null when not found
*/
public static String getKeyStoreProvider(final String keyStoreType) {
final String storeType = StringUtils.upperCase(keyStoreType);
return KEY_STORE_TYPE_PROVIDERS.get(storeType);
}
/**
* Returns an empty KeyStore backed by the appropriate provider
*
* @param keyStoreType the keyStoreType
* @return an empty KeyStore
* @throws KeyStoreException if a KeyStore of the given type cannot be instantiated
*/
public static KeyStore getKeyStore(final String keyStoreType) throws KeyStoreException {
final String keyStoreProvider = getKeyStoreProvider(keyStoreType);
if (StringUtils.isNotEmpty(keyStoreProvider)) {
try {
return KeyStore.getInstance(keyStoreType, keyStoreProvider);
} catch (final Exception e) {
logger.error("KeyStore Type [{}] Provider [{}] instance creation failed", keyStoreType, keyStoreProvider, e);
}
}
return KeyStore.getInstance(keyStoreType);
}
/**
* Returns an empty KeyStore for Secret Keys backed by the appropriate provider
*
* @param keystoreTypeName Keystore Type Name
* @return an empty KeyStore
* @throws KeyStoreException if a KeyStore of the given type cannot be instantiated
*/
public static KeyStore getSecretKeyStore(final String keystoreTypeName) throws KeyStoreException {
final KeystoreType keystoreType = getKeystoreType(keystoreTypeName);
final String provider = SECRET_KEY_STORE_PROVIDERS.get(keystoreType);
if (provider == null) {
throw new KeyStoreException(String.format("Keystore Type [%s] does not support Secret Keys", keystoreType.getType()));
}
try {
return KeyStore.getInstance(keystoreType.getType(), provider);
} catch (final NoSuchProviderException e) {
throw new KeyStoreException(String.format("KeyStore Type [%s] Provider [%s] not found", keystoreType.getType(), provider), e);
}
}
/**
* Returns a loaded {@link KeyStore} given the provided configuration values.
*
* @param keystorePath the file path to the keystore
* @param keystorePassword the keystore password
* @param keystoreType the keystore type
* @return the loaded keystore
* @throws TlsException if there is a problem loading the keystore
*/
public static KeyStore loadKeyStore(String keystorePath, char[] keystorePassword, String keystoreType) throws TlsException {
final KeyStore keyStore;
try {
keyStore = KeyStoreUtils.getKeyStore(keystoreType);
try (final InputStream keyStoreStream = new FileInputStream(keystorePath)) {
keyStore.load(keyStoreStream, keystorePassword);
}
return keyStore;
} catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException e) {
logger.error("Encountered an error loading keystore: {}", e.getLocalizedMessage());
throw new TlsException("Error loading keystore", e);
}
}
/**
* Load {@link KeyStore} containing Secret Key entries using configured Security Provider
*
* @param keystorePath File path to KeyStore
* @param keystorePassword Password for loading KeyStore
* @param keystoreTypeName Keystore Type Name
* @return KeyStore loaded using specified configuration
* @throws TlsException Thrown when unable to load KeyStore or unsupported Keystore Type
*/
public static KeyStore loadSecretKeyStore(final String keystorePath, final char[] keystorePassword, final String keystoreTypeName) throws TlsException {
try {
final KeyStore keyStore = getSecretKeyStore(keystoreTypeName);
try (final InputStream keyStoreStream = new FileInputStream(keystorePath)) {
keyStore.load(keyStoreStream, keystorePassword);
}
return keyStore;
} catch (final GeneralSecurityException|IOException e) {
throw new TlsException(String.format("Loading Secret Keystore [%s] Type [%s] Failed", keystorePath, keystoreTypeName), e);
}
}
/**
* Creates a temporary Keystore and Truststore and returns it wrapped in a new TLS configuration with the given values.
*
* @param tlsConfiguration a {@link org.apache.nifi.security.util.TlsConfiguration}
* @param certDurationDays The number of days the cert should be valid
* @param dnsSubjectAlternativeNames An optional array of dnsName SANs
* @return a {@link org.apache.nifi.security.util.TlsConfiguration}
*/
public static TlsConfiguration createTlsConfigAndNewKeystoreTruststore(final TlsConfiguration tlsConfiguration, int certDurationDays,
String[] dnsSubjectAlternativeNames) throws IOException, GeneralSecurityException {
final Path keyStorePath;
final String keystorePassword = StringUtils.isNotBlank(tlsConfiguration.getKeystorePassword()) ? tlsConfiguration.getKeystorePassword() : generatePassword();
final KeystoreType keystoreType = tlsConfiguration.getKeystoreType() != null ? tlsConfiguration.getKeystoreType() : KeystoreType.PKCS12;
final String keyPassword = StringUtils.isNotBlank(tlsConfiguration.getKeyPassword()) ? tlsConfiguration.getKeyPassword() : keystorePassword;
final Path trustStorePath;
final String truststorePassword = StringUtils.isNotBlank(tlsConfiguration.getTruststorePassword()) ? tlsConfiguration.getTruststorePassword() : generatePassword();
final KeystoreType truststoreType = tlsConfiguration.getTruststoreType() != null ? tlsConfiguration.getTruststoreType() : KeystoreType.PKCS12;
// Create temporary Keystore file
try {
keyStorePath = generateTempKeystorePath(keystoreType);
} catch (IOException e) {
logger.error(KEYSTORE_ERROR_MSG, e);
throw new UncheckedIOException(KEYSTORE_ERROR_MSG, e);
}
// Create temporary Truststore file
try {
trustStorePath = generateTempTruststorePath(truststoreType);
} catch (IOException e) {
logger.error(TRUSTSTORE_ERROR_MSG, e);
throw new UncheckedIOException(TRUSTSTORE_ERROR_MSG, e);
}
// Create X509 Certificate
final X509Certificate clientCert = createKeyStoreAndGetX509Certificate(KEY_ALIAS, keystorePassword, keyPassword,
keyStorePath.toString(), keystoreType, certDurationDays, dnsSubjectAlternativeNames);
// Create Truststore
createTrustStore(clientCert, CERT_ALIAS, truststorePassword, trustStorePath.toString(), truststoreType);
return new StandardTlsConfiguration(
keyStorePath.toString(),
keystorePassword,
keyPassword,
keystoreType,
trustStorePath.toString(),
truststorePassword,
truststoreType,
TlsPlatform.getLatestProtocol());
}
/**
* Returns the {@link KeyManagerFactory} from the provided {@link KeyStore} object, initialized with the key or keystore password.
*
* @param keyStore the loaded keystore
* @param keystorePassword the keystore password
* @param keyPassword the key password
* @return the key manager factory
* @throws TlsException if there is a problem initializing or reading from the keystore
*/
public static KeyManagerFactory getKeyManagerFactoryFromKeyStore(KeyStore keyStore, char[] keystorePassword, char[] keyPassword) throws TlsException {
try {
final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
if (keyPassword == null) {
keyManagerFactory.init(keyStore, keystorePassword);
} else {
keyManagerFactory.init(keyStore, keyPassword);
}
return keyManagerFactory;
} catch (NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException e) {
logger.error("Encountered an error loading keystore: {}", e.getLocalizedMessage());
throw new TlsException("Error loading keystore", e);
}
}
/**
* Returns the initialized {@link KeyManagerFactory}.
*
* @param tlsConfiguration the TLS configuration
* @return the initialized key manager factory
* @throws TlsException if there is a problem initializing or reading from the keystore
*/
public static KeyManagerFactory loadKeyManagerFactory(TlsConfiguration tlsConfiguration) throws TlsException {
return loadKeyManagerFactory(tlsConfiguration.getKeystorePath(), tlsConfiguration.getKeystorePassword(),
tlsConfiguration.getFunctionalKeyPassword(), tlsConfiguration.getKeystoreType().getType());
}
/**
* Returns the initialized {@link KeyManagerFactory}.
*
* @param keystorePath the file path to the keystore
* @param keystorePassword the keystore password
* @param keyPassword the key password
* @param keystoreType the keystore type
* @return the initialized key manager factory
* @throws TlsException if there is a problem initializing or reading from the keystore
*/
public static KeyManagerFactory loadKeyManagerFactory(String keystorePath, String keystorePassword, String keyPassword, String keystoreType) throws TlsException {
if (StringUtils.isEmpty(keystorePassword)) {
throw new IllegalArgumentException("The keystore password cannot be null or empty");
}
final char[] keystorePasswordChars = keystorePassword.toCharArray();
final char[] keyPasswordChars = (StringUtils.isNotEmpty(keyPassword)) ? keyPassword.toCharArray() : keystorePasswordChars;
KeyStore keyStore = loadKeyStore(keystorePath, keystorePasswordChars, keystoreType);
return getKeyManagerFactoryFromKeyStore(keyStore, keystorePasswordChars, keyPasswordChars);
}
/**
* Returns a loaded {@link KeyStore} (acting as a truststore) given the provided configuration values.
*
* @param truststorePath the file path to the truststore
* @param truststorePassword the truststore password
* @param truststoreType the truststore type
* @return the loaded truststore
* @throws TlsException if there is a problem loading the truststore
*/
public static KeyStore loadTrustStore(String truststorePath, char[] truststorePassword, String truststoreType) throws TlsException {
final KeyStore trustStore;
try {
trustStore = KeyStoreUtils.getKeyStore(truststoreType);
try (final InputStream trustStoreStream = new FileInputStream(truststorePath)) {
trustStore.load(trustStoreStream, truststorePassword);
}
return trustStore;
} catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException e) {
logger.error("Encountered an error loading truststore: {}", e.getLocalizedMessage());
throw new TlsException("Error loading truststore", e);
}
}
/**
* Returns the {@link TrustManagerFactory} from the provided {@link KeyStore} object, initialized.
*
* @param trustStore the loaded truststore
* @return the trust manager factory
* @throws TlsException if there is a problem initializing or reading from the truststore
*/
public static TrustManagerFactory getTrustManagerFactoryFromTrustStore(KeyStore trustStore) throws TlsException {
try {
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
return trustManagerFactory;
} catch (NoSuchAlgorithmException | KeyStoreException e) {
logger.error("Encountered an error loading truststore: {}", e.getLocalizedMessage());
throw new TlsException("Error loading truststore", e);
}
}
/**
* Returns the initialized {@link TrustManagerFactory}.
*
* @param tlsConfiguration the TLS configuration
* @return the initialized trust manager factory
* @throws TlsException if there is a problem initializing or reading from the truststore
*/
public static TrustManagerFactory loadTrustManagerFactory(TlsConfiguration tlsConfiguration) throws TlsException {
return loadTrustManagerFactory(tlsConfiguration.getTruststorePath(), tlsConfiguration.getTruststorePassword(), tlsConfiguration.getTruststoreType().getType());
}
/**
* Returns the initialized {@link TrustManagerFactory}.
*
* @param truststorePath the file path to the truststore
* @param truststorePassword the truststore password
* @param truststoreType the truststore type
* @return the initialized trust manager factory
* @throws TlsException if there is a problem initializing or reading from the truststore
*/
public static TrustManagerFactory loadTrustManagerFactory(String truststorePath, String truststorePassword, String truststoreType) throws TlsException {
// Bouncy Castle PKCS12 type requires a password
if (truststoreType.equalsIgnoreCase(KeystoreType.PKCS12.getType()) && StringUtils.isBlank(truststorePassword)) {
throw new IllegalArgumentException("A PKCS12 Truststore Type requires a password");
}
// Legacy truststore passwords can be empty
final char[] truststorePasswordChars = StringUtils.isNotBlank(truststorePassword) ? truststorePassword.toCharArray() : null;
KeyStore trustStore = loadTrustStore(truststorePath, truststorePasswordChars, truststoreType);
return getTrustManagerFactoryFromTrustStore(trustStore);
}
/**
* Returns true if the given keystore can be loaded using the given keystore type and password. Returns false otherwise.
*
* @param keystore the keystore to validate
* @param keystoreType the type of the keystore
* @param password the password to access the keystore
* @return true if valid; false otherwise
*/
public static boolean isStoreValid(final URL keystore, final KeystoreType keystoreType, final char[] password) {
if (keystore == null) {
throw new IllegalArgumentException("Keystore may not be null");
} else if (keystoreType == null) {
throw new IllegalArgumentException("Keystore type may not be null");
} else if (password == null) {
throw new IllegalArgumentException("Password may not be null");
}
BufferedInputStream bis = null;
final KeyStore ks;
try {
// Load the keystore
bis = new BufferedInputStream(keystore.openStream());
ks = KeyStoreUtils.getKeyStore(keystoreType.name());
ks.load(bis, password);
return true;
} catch (Exception e) {
return false;
} finally {
if (bis != null) {
try {
bis.close();
} catch (final IOException ioe) {
logger.warn("Failed to close input stream", ioe);
}
}
}
}
/**
* Returns true if the given keystore can be loaded using the given keystore type and password and the default
* (first) alias can be retrieved with the key-specific password. Returns false otherwise.
*
* @param keystore the keystore to validate
* @param keystoreType the type of the keystore
* @param password the password to access the keystore
* @param keyPassword the password to access the specific key
* @return true if valid; false otherwise
*/
public static boolean isKeyPasswordCorrect(final URL keystore, final KeystoreType keystoreType, final char[] password, final char[] keyPassword) {
if (keystore == null) {
throw new IllegalArgumentException("Keystore may not be null");
} else if (keystoreType == null) {
throw new IllegalArgumentException("Keystore type may not be null");
} else if (password == null) {
throw new IllegalArgumentException("Password may not be null");
}
BufferedInputStream bis = null;
final KeyStore ks;
try {
// Load the keystore
bis = new BufferedInputStream(keystore.openStream());
ks = KeyStoreUtils.getKeyStore(keystoreType.name());
ks.load(bis, password);
// Determine the default alias
String alias = ks.aliases().nextElement();
try {
ks.getKey(alias, keyPassword);
return true;
} catch (UnrecoverableKeyException e) {
logger.warn("Tried to access a key in keystore " + keystore + " with a key password that failed");
return false;
}
} catch (Exception e) {
return false;
} finally {
if (bis != null) {
try {
bis.close();
} catch (final IOException ioe) {
logger.warn("Failed to close input stream", ioe);
}
}
}
}
/**
* Get Keystore Type based on file extension defaults to returning PKCS12
*
* @param keystorePath Path to KeyStore
* @return Keystore Type defaults to PKCS12
*/
public static KeystoreType getKeystoreTypeFromExtension(final String keystorePath) {
KeystoreType keystoreType = KeystoreType.PKCS12;
for (final Map.Entry<KeystoreType, String> keystoreTypeEntry : KEY_STORE_EXTENSIONS.entrySet()) {
final String extension = keystoreTypeEntry.getValue();
if (StringUtils.endsWithIgnoreCase(keystorePath, extension)) {
keystoreType = keystoreTypeEntry.getKey();
break;
}
}
return keystoreType;
}
/**
* Is Secret Key Entry supported for specified Keystore Type
*
* @param keystoreType Keystore Type
* @return Secret Key Entry supported status
*/
public static boolean isSecretKeyEntrySupported(final KeystoreType keystoreType) {
return SECRET_KEY_STORE_PROVIDERS.containsKey(keystoreType);
}
public static String sslContextToString(SSLContext sslContext) {
return new ToStringBuilder(sslContext)
.append("protocol", sslContext.getProtocol())
.append("provider", sslContext.getProvider().toString())
.toString();
}
public static String sslServerSocketToString(SSLServerSocket sslServerSocket) {
return new ToStringBuilder(sslServerSocket)
.append("enabledProtocols", sslServerSocket.getEnabledProtocols())
.append("needClientAuth", sslServerSocket.getNeedClientAuth())
.append("wantClientAuth", sslServerSocket.getWantClientAuth())
.append("useClientMode", sslServerSocket.getUseClientMode())
.toString();
}
/**
* Loads the Keystore and returns a X509 Certificate with the given values.
*
* @param alias the certificate alias
* @param keyStorePassword the keystore password
* @param keyPassword the key password
* @param keyStorePath the keystore path
* @param keyStoreType the keystore type
* @param dnsSubjectAlternativeNames An optional array of dnsName SANs
* @param certDurationDays the duration of the validity of the certificate, in days
* @return a {@link X509Certificate}
*/
private static X509Certificate createKeyStoreAndGetX509Certificate(
final String alias, final String keyStorePassword, final String keyPassword, final String keyStorePath,
final KeystoreType keyStoreType, int certDurationDays, String[] dnsSubjectAlternativeNames)
throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
try (final FileOutputStream outputStream = new FileOutputStream(keyStorePath)) {
final KeyPair keyPair = KeyPairGenerator.getInstance(KEY_ALGORITHM).generateKeyPair();
final X509Certificate selfSignedCert = CertificateUtils.generateSelfSignedX509Certificate(
keyPair, CERT_DN, SIGNING_ALGORITHM, certDurationDays, dnsSubjectAlternativeNames
);
final KeyStore keyStore = loadEmptyKeyStore(keyStoreType);
keyStore.setKeyEntry(alias, keyPair.getPrivate(), keyPassword.toCharArray(), new Certificate[]{selfSignedCert});
keyStore.store(outputStream, keyStorePassword.toCharArray());
return selfSignedCert;
}
}
/**
* Loads the Truststore with the given values.
*
* @param cert the certificate
* @param alias the certificate alias
* @param password the truststore password
* @param path the truststore path
* @param truststoreType the truststore type
*/
private static void createTrustStore(final X509Certificate cert,
final String alias, final String password, final String path, final KeystoreType truststoreType)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException {
try (final FileOutputStream outputStream = new FileOutputStream(path)) {
final KeyStore trustStore = loadEmptyKeyStore(truststoreType);
trustStore.setCertificateEntry(alias, cert);
trustStore.store(outputStream, password.toCharArray());
} catch (IOException e) {
throw new UncheckedIOException(TRUSTSTORE_ERROR_MSG, e);
}
}
/**
* Generates a temporary keystore file and returns the path.
*
* @param keystoreType the Keystore type
* @return a Path
*/
private static Path generateTempKeystorePath(KeystoreType keystoreType) throws IOException {
return Files.createTempFile(TEST_KEYSTORE_PREFIX, getKeystoreExtension(keystoreType));
}
/**
* Generates a temporary truststore file and returns the path.
*
* @param truststoreType the Truststore type
* @return a Path
*/
private static Path generateTempTruststorePath(KeystoreType truststoreType) throws IOException {
return Files.createTempFile(TEST_TRUSTSTORE_PREFIX, getKeystoreExtension(truststoreType));
}
/**
* Loads and returns an empty Keystore backed by the appropriate provider.
*
* @param keyStoreType the keystore type
* @return an empty keystore
* @throws KeyStoreException if a keystore of the given type cannot be instantiated
*/
private static KeyStore loadEmptyKeyStore(final KeystoreType keyStoreType) throws KeyStoreException, CertificateException, NoSuchAlgorithmException {
try {
final KeyStore keyStore = getKeyStore(keyStoreType.getType());
keyStore.load(null, null);
return keyStore;
} catch (final IOException e) {
throw new UncheckedIOException("Error loading keystore", e);
}
}
/**
* Returns the Keystore extension given the Keystore type.
*
* @param keystoreType the keystore type
* @return the keystore extension
*/
private static String getKeystoreExtension(KeystoreType keystoreType) {
return KEY_STORE_EXTENSIONS.get(keystoreType);
}
/**
* Generates a random Hex-encoded password.
*
* @return a password as a Hex-encoded String
*/
private static String generatePassword() {
final byte[] password = new byte[PASSWORD_LENGTH];
new SecureRandom().nextBytes(password);
return Hex.encodeHexString(password);
}
private static KeystoreType getKeystoreType(final String keystoreTypeName) {
final String keystoreTypeFilter = keystoreTypeName.toUpperCase();
final Optional<KeystoreType> foundKeystoreType = Arrays.stream(KeystoreType.values())
.filter(keystoreType -> keystoreType.getType().equals(keystoreTypeFilter))
.findFirst();
return foundKeystoreType.orElseThrow(() -> new IllegalArgumentException(String.format("Keystore Type [%s] not found", keystoreTypeFilter)));
}
}