package org.apereo.cas.util.crypto;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.core.io.Resource;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.Security;
import java.security.spec.PKCS8EncodedKeySpec;
/**
* Factory Bean for creating a private key from a file.
*
* @author Scott Battaglia
* @since 3.1
*/
public class PrivateKeyFactoryBean extends AbstractFactoryBean<PrivateKey> {
private static final Logger LOGGER = LoggerFactory.getLogger(PrivateKeyFactoryBean.class);
static {
Security.addProvider(new BouncyCastleProvider());
}
private Resource location;
private String algorithm;
@Override
protected PrivateKey createInstance() throws Exception {
PrivateKey key = readPemPrivateKey();
if (key == null) {
LOGGER.debug("[{}] is not in PEM format. Trying next...", this.location.getFile());
key = readDERPrivateKey();
}
return key;
}
private PrivateKey readPemPrivateKey() throws Exception {
LOGGER.debug("Attempting to read [{}] as PEM", this.location.getFile());
try (BufferedReader br = new BufferedReader(new FileReader(this.location.getFile()))) {
final PEMParser pp = new PEMParser(br);
final PEMKeyPair pemKeyPair = (PEMKeyPair) pp.readObject();
final KeyPair kp = new JcaPEMKeyConverter().getKeyPair(pemKeyPair);
return kp.getPrivate();
} catch (final Exception e) {
LOGGER.debug(e.getMessage(), e);
return null;
}
}
private PrivateKey readDERPrivateKey() throws Exception {
LOGGER.debug("Attempting to read [{}] as DER", this.location.getFile());
try (InputStream privKey = this.location.getInputStream()) {
final byte[] bytes = new byte[privKey.available()];
privKey.read(bytes);
final PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(bytes);
final KeyFactory factory = KeyFactory.getInstance(this.algorithm);
return factory.generatePrivate(privSpec);
}
}
@Override
public Class getObjectType() {
return PrivateKey.class;
}
public void setLocation(final Resource location) {
this.location = location;
}
public void setAlgorithm(final String algorithm) {
this.algorithm = algorithm;
}
public Resource getLocation() {
return this.location;
}
public String getAlgorithm() {
return this.algorithm;
}
}