package org.cloudfoundry.identity.uaa.util;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class KeyWithCert {
private X509Certificate cert;
private KeyPair pkey;
public KeyWithCert(String certificate) throws CertificateException {
loadCertificate(certificate);
}
public KeyWithCert(String key, String passphrase, String certificate) throws CertificateException {
if(passphrase == null) {
passphrase = "";
}
PEMParser pemParser = new PEMParser(new InputStreamReader(new ByteArrayInputStream(key.getBytes())));
try {
Object object = pemParser.readObject();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
if (object instanceof PEMEncryptedKeyPair) {
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(passphrase.toCharArray());
pkey = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
}
else if (object instanceof PEMKeyPair) {
pkey = converter.getKeyPair((PEMKeyPair) object);
}
else if (object instanceof PrivateKeyInfo) {
PrivateKey privKey = converter.getPrivateKey((PrivateKeyInfo) object);
pkey = new KeyPair(null, privKey);
}
}
catch (IOException ex) {
throw new CertificateException("Failed to read private key.", ex);
}
finally {
try {
pemParser.close();
}
catch (IOException e) {
throw new CertificateException("Failed to close key reader", e);
}
}
if(pkey == null) {
throw new CertificateException("Failed to read private key. The security provider could not parse it.");
}
loadCertificate(certificate);
if (!cert.getPublicKey().equals(pkey.getPublic())) {
throw new CertificateException("Certificate does not match private key.");
}
}
public void loadCertificate(String certificate) throws CertificateException {
PEMParser pemParser;
pemParser = new PEMParser(new InputStreamReader(new ByteArrayInputStream(certificate.getBytes())));
try {
Object object = pemParser.readObject();
if (object instanceof X509CertificateHolder) {
cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate((X509CertificateHolder)object);
}
else {
throw new CertificateException("Unsupported certificate type, not an X509CertificateHolder.");
}
}
catch (IOException ex) {
throw new CertificateException("Failed to read certificate.", ex);
}
finally {
try {
pemParser.close();
}
catch (IOException e) {
throw new CertificateException("Failed to close certificate reader.", e);
}
}
if(cert == null) {
throw new CertificateException("Failed to read certificate. The security provider could not parse it.");
}
}
public X509Certificate getCert() {
return cert;
}
public KeyPair getPkey() {
return pkey;
}
}