/**
* Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.seed.core.internal.crypto;
import com.google.common.base.Strings;
import org.seedstack.seed.SeedException;
import org.seedstack.seed.crypto.CryptoConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
/**
* This class allows to load a KeyStore from a file. It supports any type of KeyStore or provider.
*/
class KeyStoreLoader {
private static final Logger LOGGER = LoggerFactory.getLogger(KeyStoreLoader.class);
KeyStore load(String name, CryptoConfig.KeyStoreConfig ksConfig) {
String path = ksConfig.getPath();
if (Strings.isNullOrEmpty(name) || Strings.isNullOrEmpty(path) || Strings.isNullOrEmpty(ksConfig.getPassword())) {
throw SeedException.createNew(CryptoErrorCode.KEYSTORE_CONFIGURATION_ERROR)
.put("ksName", name)
.put("path", path);
}
return loadFromInputStream(name, getInputStream(name, path), ksConfig);
}
private InputStream getInputStream(String name, String path) {
FileInputStream inputStream;
try {
inputStream = new FileInputStream(path);
} catch (FileNotFoundException e) {
throw SeedException.wrap(e, CryptoErrorCode.KEYSTORE_NOT_FOUND).put("name", name).put("path", path);
}
return inputStream;
}
private KeyStore loadFromInputStream(String name, InputStream inputStream, CryptoConfig.KeyStoreConfig ksConfig) {
KeyStore ks;
String type = ksConfig.getType();
String provider = ksConfig.getProvider();
try {
if (type == null || "".equals(type)) {
type = KeyStore.getDefaultType();
}
if (provider == null || "".equals(provider)) {
ks = KeyStore.getInstance(type);
} else {
ks = KeyStore.getInstance(type, provider);
}
ks.load(inputStream, ksConfig.getPassword().toCharArray());
} catch (KeyStoreException e) {
throw SeedException.wrap(e, CryptoErrorCode.KEYSTORE_TYPE_UNAVAILABLE)
.put("ksName", name)
.put("type", type);
} catch (NoSuchProviderException e) {
throw SeedException.wrap(e, CryptoErrorCode.NO_KEYSTORE_PROVIDER)
.put("ksName", name)
.put("provider", provider);
} catch (NoSuchAlgorithmException e) {
throw SeedException.wrap(e, CryptoErrorCode.ALGORITHM_CANNOT_BE_FOUND)
.put("ksName", name);
} catch (CertificateException e) {
throw SeedException.wrap(e, CryptoErrorCode.UNABLE_TO_LOAD_CERTIFICATE)
.put("ksName", name);
} catch (IOException e) {
throw SeedException.wrap(e, e.getCause() instanceof UnrecoverableKeyException ? CryptoErrorCode.INCORRECT_PASSWORD : CryptoErrorCode.UNEXPECTED_EXCEPTION)
.put("ksName", name);
} finally {
try {
inputStream.close();
} catch (IOException e) {
LOGGER.warn("Unable to close key store input stream", e);
}
}
return ks;
}
}