package mx.bigdata.sat.security;
import com.google.common.io.ByteStreams;
import lombok.Getter;
import mx.bigdata.sat.exceptions.KeyException;
import org.apache.commons.ssl.PKCS8Key;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
/**
* Created with IntelliJ IDEA.
* User: Gerardo Aquino
* Date: 3/06/13
*/
public class PrivateKeyLoader implements KeyLoader {
@Getter
PrivateKey key;
public PrivateKeyLoader(String privateKeyLocation, String keyPassword) {
this.setPrivateKey(privateKeyLocation, keyPassword);
}
public PrivateKeyLoader(InputStream privateKeyInputStream, String keyPassword) {
this.setPrivateKey(privateKeyInputStream, keyPassword);
}
/**
* @param privateKeyLocation private key located in filesystem
* @param keyPassword private key password
*
* @throws KeyException thrown when any security exception occurs
*/
public void setPrivateKey(String privateKeyLocation, String keyPassword) {
InputStream privateKeyInputStream = null;
try {
privateKeyInputStream = new FileInputStream(privateKeyLocation);
}catch (FileNotFoundException fnfe){
throw new KeyException("La ubicación del archivo de la llave privada es incorrecta", fnfe.getCause());
}
this.setPrivateKey(privateKeyInputStream, keyPassword);
}
/**
*
* @param privateKeyInputStream private key's input stream
* @param keyPassword private key password
*
* @throws KeyException thrown when any security exception occurs
*/
public void setPrivateKey(InputStream privateKeyInputStream, String keyPassword) {
byte[] privateKeyByte = this.extractProtectedPrivateKey(privateKeyInputStream, keyPassword);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
try {
this.key = KeyFactory.getInstance("RSA").generatePrivate(pkcs8EncodedKeySpec);
}catch (GeneralSecurityException gse) {
throw new KeyException(
"Error al obtener la información del certificado debido a su codificación",
gse.getCause());
}
}
private byte[] extractProtectedPrivateKey(InputStream privateKeyInputStream, String keyPassword) {
byte[] bytes;
try {
if(keyPassword == null) {
bytes = ByteStreams.toByteArray(privateKeyInputStream);
} else {
bytes = new PKCS8Key(privateKeyInputStream, keyPassword.toCharArray()).getDecryptedBytes();
}
} catch (GeneralSecurityException e) {
throw new KeyException("La contraseña del certificado no es correcta", e.getCause());
} catch (IOException ioe){
throw new KeyException(ioe.getMessage(), ioe.getCause());
}
return bytes;
}
}