/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.bean;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import org.cryptacular.CryptoException;
import org.cryptacular.StreamException;
import org.cryptacular.io.Resource;
/**
* Factory bean that produces a {@link KeyStore} from a file or URI.
*
* @author Middleware Services
*/
public class KeyStoreFactoryBean implements FactoryBean<KeyStore>
{
/** Default keystore type, {@value}. */
public static final String DEFAULT_TYPE = "JCEKS";
/** Keystore type, e.g. JKS, JCEKS, BKS. */
private String type = DEFAULT_TYPE;
/** Resource that provides encoded keystore data. */
private Resource resource;
/** Keystore password. */
private String password;
/** Creates a new instance. */
public KeyStoreFactoryBean() {}
/**
* Creates a new instance by specifying all properties.
*
* @param resource Resource containing encoded keystore data.
* @param type Keystore type, e.g. JCEKS.
* @param password Password used to decrypt key entry in keystore.
*/
public KeyStoreFactoryBean(final Resource resource, final String type, final String password)
{
setResource(resource);
setType(type);
setPassword(password);
}
/** @return Keystore type. */
public String getType()
{
return type;
}
/**
* Sets the keystore type.
*
* @param type JCEKS (default), JKS, PKCS12, or BKS. <strong>NOTE:</strong> BKS type is supported only when BC
* provider is installed.
*/
public void setType(final String type)
{
this.type = type;
}
/** @return Resource that provides encoded keystore data. */
public Resource getResource()
{
return resource;
}
/**
* Sets the resource that provides encoded keystore data.
*
* @param resource Keystore resource.
*/
public void setResource(final Resource resource)
{
this.resource = resource;
}
/**
* Sets the keystore password required to decrypt an encrypted keystore.
*
* @param password Keystore password.
*/
public void setPassword(final String password)
{
this.password = password;
}
@Override
public KeyStore newInstance()
{
if (resource == null) {
throw new IllegalStateException("Must provide resource.");
}
final KeyStore store;
try {
store = KeyStore.getInstance(type);
} catch (KeyStoreException e) {
String message = "Unsupported keystore type " + type;
if ("BKS".equalsIgnoreCase(type)) {
message += ". Is BC provider installed?";
}
throw new CryptoException(message, e);
}
try {
store.load(resource.getInputStream(), password.toCharArray());
} catch (CertificateException | NoSuchAlgorithmException e) {
throw new CryptoException("Error loading keystore", e);
} catch (IOException e) {
throw new StreamException(e);
}
return store;
}
}