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