Utilities.java
package io.mersel.dss.signer.api.util;
import io.mersel.dss.signer.api.util.xml.SecureXmlFactories;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Utilities {
private static final Logger LOGGER = LoggerFactory.getLogger(Utilities.class);
public static Document LoadXMLFromInputStream(InputStream inputStream) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = SecureXmlFactories.newDocumentBuilderFactory();
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(inputStream);
}
public static byte[] ZipBytes(String filename, byte[] input) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
ZipEntry entry = new ZipEntry(filename);
entry.setSize(input.length);
zos.putNextEntry(entry);
zos.write(input);
zos.closeEntry();
zos.close();
return baos.toByteArray();
}
public static List<X509Certificate> BuildCertificateChainOnline(X509Certificate cert) throws Exception {
List<X509Certificate> chain = new ArrayList<>();
chain.add(cert);
X509Certificate issuerCert;
while ((issuerCert = fetchIssuerCertificate(cert)) != null) {
chain.add(issuerCert);
cert = issuerCert;
if (cert.getSubjectX500Principal().equals(cert.getIssuerX500Principal())) {
LOGGER.info("✅ Root CA'ya ulaşıldı: {}", cert.getSubjectX500Principal());
break;
}
}
return chain;
}
private static X509Certificate fetchIssuerCertificate(X509Certificate cert) throws Exception {
String aiaUrl = getAiaIssuerUrl(cert);
if (aiaUrl == null) {
throw new Exception("Issuer sertifikası için AIA URL bulunamadı!");
}
LOGGER.info("📥 Issuer sertifikası indiriliyor: {}", aiaUrl);
return downloadCertificate(aiaUrl);
}
private static String getAiaIssuerUrl(X509Certificate cert) throws Exception {
byte[] aiaExt = cert.getExtensionValue(Extension.authorityInfoAccess.getId());
if (aiaExt == null) return null;
ASN1Sequence seq = ASN1Sequence.getInstance(JcaX509ExtensionUtils.parseExtensionValue(aiaExt));
for (ASN1Encodable encodable : seq.toArray()) {
ASN1Sequence subSeq = ASN1Sequence.getInstance(encodable);
if (subSeq.size() < 2) continue;
ASN1ObjectIdentifier id = (ASN1ObjectIdentifier) subSeq.getObjectAt(0);
if (id.getId().equals("1.3.6.1.5.5.7.48.2")) { // CA Issuer OID
GeneralName generalName = GeneralName.getInstance(subSeq.getObjectAt(1));
return ((DERIA5String) generalName.getName()).getString();
}
}
return null;
}
private static X509Certificate downloadCertificate(String urlStr) throws Exception {
URL url = new URL(urlStr);
try (InputStream in = url.openStream()) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
return (X509Certificate) cf.generateCertificate(in);
}
}
public static X509Certificate LoadX509Certificate(String filePath) throws Exception {
try (InputStream in = Files.newInputStream(Paths.get(filePath))) {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
return (X509Certificate) factory.generateCertificate(in);
}
}
public static void CheckIsDateValid(X509Certificate cert) {
Date certStartTime = cert.getNotBefore();
Date certEndTime = cert.getNotAfter();
Date now = Calendar.getInstance().getTime();
if (!(now.after(certStartTime) && now.before(certEndTime))) {
throw new RuntimeException("Certificate is not valid");
}
}
}