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