I took inspiration from the shell script shared by @adrock20 and i implemented it in java
import javaioBufferedInputStream;
import javaioFileInputStream;
import java.io.FileOutputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.CertificateFactory;
import java.security.certX509Certificate;
import java.util.Enumeration;
import javax.net.ssl.KeyManagerFactory;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.AccessDescription;
import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
public class CertificateUtil {
public static void convertPfxToFullChainJks(String pfxPath, String password, String jksPath) {
String alias = getX509CertificateAliasFromPfxFile(pfxPath, password);
X509Certificate certificate = getX509CertificateFromPfxFile(pfxPath, password);
PrivateKey privateKey = getPrivateKeyFromPfxFile(pfxPath, password);
String intermediateCertificateUrl = getAuthorityCertificateUrl(certificate);
X509Certificate intermediateCertificate = downloadCertificateFromUrl(intermediateCertificateUrl);
String rootCertificateUrl = getAuthorityCertificateUrl(intermediateCertificate);
X509Certificate rootCertificate = downloadCertificateFromUrl(rootCertificateUrl);
createFullChainJks(jksPath, alias, password, certificate, privateKey, intermediateCertificate, rootCertificate);
}
private static void createFullChainJks(String jksPath, String alias, String password, X509Certificate certificate, PrivateKey privateKey,
X509Certificate intermediateCertificate,
X509Certificate rootCertificate) throws Exception {
try {
try (FileOutputStream fos = new FileOutputStream(jksPath)) {
KeyStore ks = ("JKS");
(null, ());
X509Certificate[] certificateChain = new X509Certificate[]{certificate, intermediateCertificate, rootCertificate};
(alias, privateKey, (), certificateChain);
(fos, ());
}
} catch (Exception e) {
throw new Exception("Failed to create full chain jks", e);
}
}
private static String getX509CertificateAliasFromPfxFile(String pfxPath, String password) throws Exception {
try {
KeyManagerFactory kmf = ("SunX509");
KeyStore keystore = ("PKCS12");
(new FileInputStream(pfxPath), ());
(keystore, ());
Enumeration<String> aliases = ();
while (aliases.hasMoreElements()) {
String alias = ();
if ("X.509".equals((alias).getType())) {
return alias;
}
}
} catch (Exception e) {
throw new Exception("Failed to retrieve X509 certificate alias from PFX file", e);
}
throw new Exception("No valid X509 certificate alias found in the PFX file");
}
private static X509Certificate getX509CertificateFromPfxFile(String pfxPath, String password) throws Exception {
try {
KeyManagerFactory kmf = ("SunX509");
KeyStore keystore = ("PKCS12");
(new FileInputStream(pfxPath), ());
(keystore, ());
Enumeration<String> aliases = ();
while (aliases.hasMoreElements()) {
String alias = ();
if ("X.509".equals((alias).getType())) {
return (X509Certificate) (alias);
}
}
} catch (Exception e) {
throw new Exception("Failed to retrieve X509 certificate from PFX file", e);
}
throw new Exception("No valid X509 certificate found in the PFX file");
}
private static PrivateKey getPrivateKeyFromPfxFile(String pfxPath, String password) throws Exception {
try {
KeyManagerFactory kmf = ("SunX509");
KeyStore keystore = ("PKCS12");
(new FileInputStream(pfxPath), ());
(keystore, ());
Enumeration<String> aliases = ();
while (aliases.hasMoreElements()) {
String alias = ();
if ("X.509".equals((alias).getType())) {
privateKeyEntry = () (alias,
new (()));
return ();
}
}
} catch (Exception e) {
throw new Exception("Failed to retrieve private key from PFX file", e);
}
throw new Exception("No valid private key found in the PFX file");
}
private static X509Certificate downloadCertificateFromUrl(String certificateUrlString) throws Exception {
try {
URL certificateUrl = new URL(certificateUrlString);
String filename = ().split("/")[2];
String filePath = "target/" + filename;
try (BufferedInputStream in = new BufferedInputStream(certificateUrl.openStream());
FileOutputStream fileOutputStream = new FileOutputStream(filePath)) {
byte[] dataBuffer = new byte[1024];
int bytesRead;
while ((bytesRead = (dataBuffer, 0, 1024)) != -1) {
(dataBuffer, 0, bytesRead);
}
}
try (FileInputStream inStream = new FileInputStream(filePath)) {
CertificateFactory cf = ("X.509");
return (X509Certificate) (inStream);
}
} catch (Exception e) {
throw new Exception("Failed to download certificate from URL", e);
}
}
private static String getAuthorityCertificateUrl(X509Certificate certificate) throws Exception {
try {
byte[] extVal = (());
if (extVal == null) {
throw new Exception("Certificate does not contain Authority Information Access extension");
}
AuthorityInformationAccess aia = ((extVal));
AccessDescription[] descriptions = ();
for (AccessDescription accessDescription : descriptions) {
final ASN1ObjectIdentifier accessMethod = ;
final boolean correctAccessMethod = ().equals(accessMethod);
if (!correctAccessMethod) {
continue;
}
final GeneralName gn = ();
if (gn.getTagNo() != GeneralName.uniformResourceIdentifier) {
continue;
}
final DERIA5String str = (DERIA5String) ((DERTaggedObject) gn.toASN1Primitive()).getBaseObject();
final String accessLocation = ();
if (accessLocation.startsWith("http")) {
return accessLocation;
}
}
} catch (Exception e) {
throw new Exception("Failed to get authority certificate URL", e);
}
throw new Exception("No valid authority certificate URL found in the certificate");
}
}