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