1 package club.wpia.gigi.util;
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.math.BigInteger;
6 import java.security.GeneralSecurityException;
7 import java.security.cert.CRLException;
8 import java.security.cert.CertificateEncodingException;
9 import java.security.cert.CertificateException;
10 import java.security.cert.X509CRL;
11 import java.security.cert.X509Certificate;
12 import java.util.HashSet;
13 import java.util.LinkedList;
16 import javax.servlet.ServletOutputStream;
18 import club.wpia.gigi.GigiApiException;
19 import club.wpia.gigi.dbObjects.CACertificate;
20 import club.wpia.gigi.dbObjects.Certificate;
21 import sun.security.pkcs.ContentInfo;
22 import sun.security.pkcs.PKCS7;
23 import sun.security.pkcs.SignerInfo;
24 import sun.security.util.DerOutputStream;
25 import sun.security.util.DerValue;
26 import sun.security.x509.AlgorithmId;
27 import sun.security.x509.X509CRLImpl;
28 import sun.security.x509.X509CertImpl;
30 public class CertExporter {
32 private CertExporter() {}
34 public static void writeCertCrt(Certificate c, ServletOutputStream out, boolean doChain, boolean includeAnchor, boolean includeLeaf) throws IOException, GeneralSecurityException, GigiApiException {
35 X509Certificate cert = c.cert();
37 out.println(PEM.encode("CERTIFICATE", cert.getEncoded()));
40 CACertificate ca = c.getParent();
41 while ( !ca.isSelfsigned()) {
42 out.println(PEM.encode("CERTIFICATE", ca.getCertificate().getEncoded()));
46 out.println(PEM.encode("CERTIFICATE", ca.getCertificate().getEncoded()));
51 public static void writeCertCer(Certificate c, ServletOutputStream out, boolean doChain, boolean includeAnchor) throws IOException, GeneralSecurityException, GigiApiException {
52 X509Certificate cert = c.cert();
54 PKCS7 p7 = toP7Chain(c);
55 p7.encodeSignedData(out);
57 out.write(cert.getEncoded());
61 private static PKCS7 toP7Chain(Certificate c) throws IOException, GeneralSecurityException, GigiApiException {
63 return generateP7Bundle(getChain(c));
67 private static PKCS7 generateP7Bundle(LinkedList<X509Certificate> ll) {
68 PKCS7 p7 = new PKCS7(new AlgorithmId[0], new ContentInfo(ContentInfo.DATA_OID, null), ll.toArray(new X509Certificate[ll.size()]), new SignerInfo[0]) {
71 public void encodeSignedData(DerOutputStream out) throws IOException {
72 DerOutputStream signedData = new DerOutputStream();
73 BigInteger version = getVersion();
74 AlgorithmId[] digestAlgorithmIds = getDigestAlgorithmIds();
75 ContentInfo contentInfo = getContentInfo();
76 X509Certificate[] certificates = getCertificates();
77 X509CRL[] crls = getCRLs();
78 SignerInfo[] signerInfos = getSignerInfos();
81 signedData.putInteger(version);
84 signedData.putOrderedSetOf(DerValue.tag_Set, digestAlgorithmIds);
87 contentInfo.encode(signedData);
89 // certificates (optional)
90 if (certificates != null && certificates.length != 0) {
91 DerOutputStream sub = new DerOutputStream();
92 // cast to X509CertImpl[] since X509CertImpl implements
94 X509CertImpl implCerts[] = new X509CertImpl[certificates.length];
95 for (int i = 0; i < certificates.length; i++) {
97 sub.write(certificates[i].getEncoded());
98 } catch (CertificateEncodingException e) {
100 throw new IOException(e);
102 if (certificates[i] instanceof X509CertImpl) {
103 implCerts[i] = (X509CertImpl) certificates[i];
106 byte[] encoded = certificates[i].getEncoded();
107 implCerts[i] = new X509CertImpl(encoded);
108 } catch (CertificateException ce) {
110 throw new IOException(ce);
115 // Add the certificate set (tagged with [0] IMPLICIT)
116 // to the signed data
117 signedData.write((byte) 0xA0, sub);
122 if (crls != null && crls.length != 0) {
123 // cast to X509CRLImpl[] since X509CRLImpl implements
125 Set<X509CRLImpl> implCRLs = new HashSet<X509CRLImpl>(crls.length);
126 for (X509CRL crl : crls) {
127 if (crl instanceof X509CRLImpl) {
128 implCRLs.add((X509CRLImpl) crl);
131 byte[] encoded = crl.getEncoded();
132 implCRLs.add(new X509CRLImpl(encoded));
133 } catch (CRLException ce) {
134 throw new IOException(ce);
139 // Add the CRL set (tagged with [1] IMPLICIT)
140 // to the signed data
141 signedData.putOrderedSetOf((byte) 0xA1, implCRLs.toArray(new X509CRLImpl[implCRLs.size()]));
145 signedData.putOrderedSetOf(DerValue.tag_Set, signerInfos);
147 // making it a signed data block
148 DerValue signedDataSeq = new DerValue(DerValue.tag_Sequence, signedData.toByteArray());
150 // making it a content info sequence
151 ContentInfo block = new ContentInfo(ContentInfo.SIGNED_DATA_OID, signedDataSeq);
153 // writing out the contentInfo sequence
161 private static LinkedList<X509Certificate> getChain(Certificate c) throws IOException, GeneralSecurityException, GigiApiException {
162 LinkedList<X509Certificate> ll = new LinkedList<>();
164 CACertificate ca = c.getParent();
165 while ( !ca.isSelfsigned()) {
166 ll.add(ca.getCertificate());
169 ll.add(ca.getCertificate());
173 public static void writeCertBundle(OutputStream out) throws IOException, GeneralSecurityException, GigiApiException {
175 CACertificate[] cs = CACertificate.getAll();
176 LinkedList<X509Certificate> ll = new LinkedList<>();
177 for (CACertificate cb : cs) {
178 if ( !cb.isSelfsigned()) {
179 ll.add(cb.getCertificate());
183 PKCS7 p7 = generateP7Bundle(ll);
184 p7.encodeSignedData(out);