• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.bouncycastle.cert;
2 
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.text.ParseException;
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.Collections;
9 import java.util.Date;
10 import java.util.HashSet;
11 import java.util.List;
12 import java.util.Set;
13 
14 import org.bouncycastle.asn1.ASN1Encodable;
15 import org.bouncycastle.asn1.ASN1EncodableVector;
16 import org.bouncycastle.asn1.ASN1GeneralizedTime;
17 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
18 import org.bouncycastle.asn1.ASN1Primitive;
19 import org.bouncycastle.asn1.DERBitString;
20 import org.bouncycastle.asn1.DERNull;
21 import org.bouncycastle.asn1.DEROutputStream;
22 import org.bouncycastle.asn1.DERSequence;
23 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
24 import org.bouncycastle.asn1.x509.AttributeCertificate;
25 import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
26 import org.bouncycastle.asn1.x509.Certificate;
27 import org.bouncycastle.asn1.x509.CertificateList;
28 import org.bouncycastle.asn1.x509.Extensions;
29 import org.bouncycastle.asn1.x509.ExtensionsGenerator;
30 import org.bouncycastle.asn1.x509.TBSCertList;
31 import org.bouncycastle.asn1.x509.TBSCertificate;
32 import org.bouncycastle.operator.ContentSigner;
33 
34 class CertUtils
35 {
36     private static Set EMPTY_SET = Collections.unmodifiableSet(new HashSet());
37     private static List EMPTY_LIST = Collections.unmodifiableList(new ArrayList());
38 
parseNonEmptyASN1(byte[] encoding)39     static ASN1Primitive parseNonEmptyASN1(byte[] encoding)
40         throws IOException
41     {
42         ASN1Primitive p = ASN1Primitive.fromByteArray(encoding);
43 
44         if (p == null)
45         {
46             throw new IOException("no content found");
47         }
48         return p;
49     }
50 
generateFullCert(ContentSigner signer, TBSCertificate tbsCert)51     static X509CertificateHolder generateFullCert(ContentSigner signer, TBSCertificate tbsCert)
52     {
53         try
54         {
55             return new X509CertificateHolder(generateStructure(tbsCert, signer.getAlgorithmIdentifier(), generateSig(signer, tbsCert)));
56         }
57         catch (IOException e)
58         {
59             throw new IllegalStateException("cannot produce certificate signature");
60         }
61     }
62 
generateFullAttrCert(ContentSigner signer, AttributeCertificateInfo attrInfo)63     static X509AttributeCertificateHolder generateFullAttrCert(ContentSigner signer, AttributeCertificateInfo attrInfo)
64     {
65         try
66         {
67             return new X509AttributeCertificateHolder(generateAttrStructure(attrInfo, signer.getAlgorithmIdentifier(), generateSig(signer, attrInfo)));
68         }
69         catch (IOException e)
70         {
71             throw new IllegalStateException("cannot produce attribute certificate signature");
72         }
73     }
74 
generateFullCRL(ContentSigner signer, TBSCertList tbsCertList)75     static X509CRLHolder generateFullCRL(ContentSigner signer, TBSCertList tbsCertList)
76     {
77         try
78         {
79             return new X509CRLHolder(generateCRLStructure(tbsCertList, signer.getAlgorithmIdentifier(), generateSig(signer, tbsCertList)));
80         }
81         catch (IOException e)
82         {
83             throw new IllegalStateException("cannot produce certificate signature");
84         }
85     }
86 
generateSig(ContentSigner signer, ASN1Encodable tbsObj)87     private static byte[] generateSig(ContentSigner signer, ASN1Encodable tbsObj)
88         throws IOException
89     {
90         OutputStream sOut = signer.getOutputStream();
91         DEROutputStream dOut = new DEROutputStream(sOut);
92 
93         dOut.writeObject(tbsObj);
94 
95         sOut.close();
96 
97         return signer.getSignature();
98     }
99 
generateStructure(TBSCertificate tbsCert, AlgorithmIdentifier sigAlgId, byte[] signature)100     private static Certificate generateStructure(TBSCertificate tbsCert, AlgorithmIdentifier sigAlgId, byte[] signature)
101     {
102         ASN1EncodableVector v = new ASN1EncodableVector();
103 
104         v.add(tbsCert);
105         v.add(sigAlgId);
106         v.add(new DERBitString(signature));
107 
108         return Certificate.getInstance(new DERSequence(v));
109     }
110 
generateAttrStructure(AttributeCertificateInfo attrInfo, AlgorithmIdentifier sigAlgId, byte[] signature)111     private static AttributeCertificate generateAttrStructure(AttributeCertificateInfo attrInfo, AlgorithmIdentifier sigAlgId, byte[] signature)
112     {
113         ASN1EncodableVector v = new ASN1EncodableVector();
114 
115         v.add(attrInfo);
116         v.add(sigAlgId);
117         v.add(new DERBitString(signature));
118 
119         return AttributeCertificate.getInstance(new DERSequence(v));
120     }
121 
generateCRLStructure(TBSCertList tbsCertList, AlgorithmIdentifier sigAlgId, byte[] signature)122     private static CertificateList generateCRLStructure(TBSCertList tbsCertList, AlgorithmIdentifier sigAlgId, byte[] signature)
123     {
124         ASN1EncodableVector v = new ASN1EncodableVector();
125 
126         v.add(tbsCertList);
127         v.add(sigAlgId);
128         v.add(new DERBitString(signature));
129 
130         return CertificateList.getInstance(new DERSequence(v));
131     }
132 
getCriticalExtensionOIDs(Extensions extensions)133     static Set getCriticalExtensionOIDs(Extensions extensions)
134     {
135         if (extensions == null)
136         {
137             return EMPTY_SET;
138         }
139 
140         return Collections.unmodifiableSet(new HashSet(Arrays.asList(extensions.getCriticalExtensionOIDs())));
141     }
142 
getNonCriticalExtensionOIDs(Extensions extensions)143     static Set getNonCriticalExtensionOIDs(Extensions extensions)
144     {
145         if (extensions == null)
146         {
147             return EMPTY_SET;
148         }
149 
150         // TODO: should probably produce a set that imposes correct ordering
151         return Collections.unmodifiableSet(new HashSet(Arrays.asList(extensions.getNonCriticalExtensionOIDs())));
152     }
153 
getExtensionOIDs(Extensions extensions)154     static List getExtensionOIDs(Extensions extensions)
155     {
156         if (extensions == null)
157         {
158             return EMPTY_LIST;
159         }
160 
161         return Collections.unmodifiableList(Arrays.asList(extensions.getExtensionOIDs()));
162     }
163 
addExtension(ExtensionsGenerator extGenerator, ASN1ObjectIdentifier oid, boolean isCritical, ASN1Encodable value)164     static void addExtension(ExtensionsGenerator extGenerator, ASN1ObjectIdentifier oid, boolean isCritical, ASN1Encodable value)
165         throws CertIOException
166     {
167         try
168         {
169             extGenerator.addExtension(oid, isCritical, value);
170         }
171         catch (IOException e)
172         {
173             throw new CertIOException("cannot encode extension: " + e.getMessage(), e);
174         }
175     }
176 
booleanToBitString(boolean[] id)177     static DERBitString booleanToBitString(boolean[] id)
178     {
179         byte[] bytes = new byte[(id.length + 7) / 8];
180 
181         for (int i = 0; i != id.length; i++)
182         {
183             bytes[i / 8] |= (id[i]) ? (1 << ((7 - (i % 8)))) : 0;
184         }
185 
186         int pad = id.length % 8;
187 
188         if (pad == 0)
189         {
190             return new DERBitString(bytes);
191         }
192         else
193         {
194             return new DERBitString(bytes, 8 - pad);
195         }
196     }
197 
bitStringToBoolean(DERBitString bitString)198     static boolean[] bitStringToBoolean(DERBitString bitString)
199     {
200         if (bitString != null)
201         {
202             byte[]          bytes = bitString.getBytes();
203             boolean[]       boolId = new boolean[bytes.length * 8 - bitString.getPadBits()];
204 
205             for (int i = 0; i != boolId.length; i++)
206             {
207                 boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
208             }
209 
210             return boolId;
211         }
212 
213         return null;
214     }
215 
recoverDate(ASN1GeneralizedTime time)216     static Date recoverDate(ASN1GeneralizedTime time)
217     {
218         try
219         {
220             return time.getDate();
221         }
222         catch (ParseException e)
223         {
224             throw new IllegalStateException("unable to recover date: " + e.getMessage());
225         }
226     }
227 
isAlgIdEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2)228     static boolean isAlgIdEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2)
229     {
230         if (!id1.getAlgorithm().equals(id2.getAlgorithm()))
231         {
232             return false;
233         }
234 
235         if (id1.getParameters() == null)
236         {
237             if (id2.getParameters() != null && !id2.getParameters().equals(DERNull.INSTANCE))
238             {
239                 return false;
240             }
241 
242             return true;
243         }
244 
245         if (id2.getParameters() == null)
246         {
247             if (id1.getParameters() != null && !id1.getParameters().equals(DERNull.INSTANCE))
248             {
249                 return false;
250             }
251 
252             return true;
253         }
254 
255         return id1.getParameters().equals(id2.getParameters());
256     }
257 }
258