]> WPIA git - gigi.git/blob - src/club/wpia/gigi/util/CertExporter.java
chg: use certificate attachment to store CRT and CSR files
[gigi.git] / src / club / wpia / gigi / util / CertExporter.java
1 package club.wpia.gigi.util;
2
3 import java.io.IOException;
4 import java.math.BigInteger;
5 import java.security.GeneralSecurityException;
6 import java.security.cert.CRLException;
7 import java.security.cert.CertificateEncodingException;
8 import java.security.cert.CertificateException;
9 import java.security.cert.X509CRL;
10 import java.security.cert.X509Certificate;
11 import java.util.HashSet;
12 import java.util.LinkedList;
13 import java.util.Set;
14
15 import javax.servlet.ServletOutputStream;
16
17 import club.wpia.gigi.GigiApiException;
18 import club.wpia.gigi.dbObjects.CACertificate;
19 import club.wpia.gigi.dbObjects.Certificate;
20 import sun.security.pkcs.ContentInfo;
21 import sun.security.pkcs.PKCS7;
22 import sun.security.pkcs.SignerInfo;
23 import sun.security.util.DerOutputStream;
24 import sun.security.util.DerValue;
25 import sun.security.x509.AlgorithmId;
26 import sun.security.x509.X509CRLImpl;
27 import sun.security.x509.X509CertImpl;
28
29 public class CertExporter {
30
31     private CertExporter() {}
32
33     public static void writeCertCrt(Certificate c, ServletOutputStream out, boolean doChain, boolean includeAnchor, boolean includeLeaf) throws IOException, GeneralSecurityException, GigiApiException {
34         X509Certificate cert = c.cert();
35         if (includeLeaf) {
36             out.println(PEM.encode("CERTIFICATE", cert.getEncoded()));
37         }
38         if (doChain) {
39             CACertificate ca = c.getParent();
40             while ( !ca.isSelfsigned()) {
41                 out.println(PEM.encode("CERTIFICATE", ca.getCertificate().getEncoded()));
42                 ca = ca.getParent();
43             }
44             if (includeAnchor) {
45                 out.println(PEM.encode("CERTIFICATE", ca.getCertificate().getEncoded()));
46             }
47         }
48     }
49
50     public static void writeCertCer(Certificate c, ServletOutputStream out, boolean doChain, boolean includeAnchor) throws IOException, GeneralSecurityException, GigiApiException {
51         X509Certificate cert = c.cert();
52         if (doChain) {
53             PKCS7 p7 = toP7Chain(c);
54             p7.encodeSignedData(out);
55         } else {
56             out.write(cert.getEncoded());
57         }
58     }
59
60     private static PKCS7 toP7Chain(Certificate c) throws IOException, GeneralSecurityException, GigiApiException {
61         LinkedList<X509Certificate> ll = getChain(c);
62         PKCS7 p7 = new PKCS7(new AlgorithmId[0], new ContentInfo(ContentInfo.DATA_OID, null), ll.toArray(new X509Certificate[ll.size()]), new SignerInfo[0]) {
63
64             @Override
65             public void encodeSignedData(DerOutputStream out) throws IOException {
66                 DerOutputStream signedData = new DerOutputStream();
67                 BigInteger version = getVersion();
68                 AlgorithmId[] digestAlgorithmIds = getDigestAlgorithmIds();
69                 ContentInfo contentInfo = getContentInfo();
70                 X509Certificate[] certificates = getCertificates();
71                 X509CRL[] crls = getCRLs();
72                 SignerInfo[] signerInfos = getSignerInfos();
73
74                 // version
75                 signedData.putInteger(version);
76
77                 // digestAlgorithmIds
78                 signedData.putOrderedSetOf(DerValue.tag_Set, digestAlgorithmIds);
79
80                 // contentInfo
81                 contentInfo.encode(signedData);
82
83                 // certificates (optional)
84                 if (certificates != null && certificates.length != 0) {
85                     DerOutputStream sub = new DerOutputStream();
86                     // cast to X509CertImpl[] since X509CertImpl implements
87                     // DerEncoder
88                     X509CertImpl implCerts[] = new X509CertImpl[certificates.length];
89                     for (int i = 0; i < certificates.length; i++) {
90                         try {
91                             sub.write(certificates[i].getEncoded());
92                         } catch (CertificateEncodingException e) {
93                             sub.close();
94                             throw new IOException(e);
95                         }
96                         if (certificates[i] instanceof X509CertImpl) {
97                             implCerts[i] = (X509CertImpl) certificates[i];
98                         } else {
99                             try {
100                                 byte[] encoded = certificates[i].getEncoded();
101                                 implCerts[i] = new X509CertImpl(encoded);
102                             } catch (CertificateException ce) {
103                                 sub.close();
104                                 throw new IOException(ce);
105                             }
106                         }
107                     }
108
109                     // Add the certificate set (tagged with [0] IMPLICIT)
110                     // to the signed data
111                     signedData.write((byte) 0xA0, sub);
112                     sub.close();
113                 }
114
115                 // CRLs (optional)
116                 if (crls != null && crls.length != 0) {
117                     // cast to X509CRLImpl[] since X509CRLImpl implements
118                     // DerEncoder
119                     Set<X509CRLImpl> implCRLs = new HashSet<X509CRLImpl>(crls.length);
120                     for (X509CRL crl : crls) {
121                         if (crl instanceof X509CRLImpl) {
122                             implCRLs.add((X509CRLImpl) crl);
123                         } else {
124                             try {
125                                 byte[] encoded = crl.getEncoded();
126                                 implCRLs.add(new X509CRLImpl(encoded));
127                             } catch (CRLException ce) {
128                                 throw new IOException(ce);
129                             }
130                         }
131                     }
132
133                     // Add the CRL set (tagged with [1] IMPLICIT)
134                     // to the signed data
135                     signedData.putOrderedSetOf((byte) 0xA1, implCRLs.toArray(new X509CRLImpl[implCRLs.size()]));
136                 }
137
138                 // signerInfos
139                 signedData.putOrderedSetOf(DerValue.tag_Set, signerInfos);
140
141                 // making it a signed data block
142                 DerValue signedDataSeq = new DerValue(DerValue.tag_Sequence, signedData.toByteArray());
143
144                 // making it a content info sequence
145                 ContentInfo block = new ContentInfo(ContentInfo.SIGNED_DATA_OID, signedDataSeq);
146
147                 // writing out the contentInfo sequence
148                 block.encode(out);
149             }
150
151         };
152         return p7;
153     }
154
155     private static LinkedList<X509Certificate> getChain(Certificate c) throws IOException, GeneralSecurityException, GigiApiException {
156         LinkedList<X509Certificate> ll = new LinkedList<>();
157         ll.add(c.cert());
158         CACertificate ca = c.getParent();
159         while ( !ca.isSelfsigned()) {
160             ll.add(ca.getCertificate());
161             ca = ca.getParent();
162         }
163         ll.add(ca.getCertificate());
164         return ll;
165     }
166
167 }