/* 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; } }