1 package org.bouncycastle.x509; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.math.BigInteger; 7 import java.security.InvalidKeyException; 8 import java.security.NoSuchAlgorithmException; 9 import java.security.NoSuchProviderException; 10 import java.security.PublicKey; 11 import java.security.Signature; 12 import java.security.SignatureException; 13 import java.security.cert.CertificateException; 14 import java.security.cert.CertificateExpiredException; 15 import java.security.cert.CertificateNotYetValidException; 16 import java.text.ParseException; 17 import java.util.ArrayList; 18 import java.util.Date; 19 import java.util.Enumeration; 20 import java.util.HashSet; 21 import java.util.List; 22 import java.util.Set; 23 24 import org.bouncycastle.asn1.ASN1Encodable; 25 import org.bouncycastle.asn1.ASN1InputStream; 26 import org.bouncycastle.asn1.ASN1Sequence; 27 import org.bouncycastle.asn1.DERBitString; 28 import org.bouncycastle.asn1.DERObjectIdentifier; 29 import org.bouncycastle.asn1.x509.AttributeCertificate; 30 import org.bouncycastle.asn1.x509.X509Extension; 31 import org.bouncycastle.asn1.x509.X509Extensions; 32 import org.bouncycastle.util.Arrays; 33 34 /** 35 * An implementation of a version 2 X.509 Attribute Certificate. 36 * @deprecated use org.bouncycastle.cert.X509AttributeCertificateHolder 37 */ 38 public class X509V2AttributeCertificate 39 implements X509AttributeCertificate 40 { 41 private AttributeCertificate cert; 42 private Date notBefore; 43 private Date notAfter; 44 45 private static AttributeCertificate getObject(InputStream in) 46 throws IOException 47 { 48 try 49 { 50 return AttributeCertificate.getInstance(new ASN1InputStream(in).readObject()); 51 } 52 catch (IOException e) 53 { 54 throw e; 55 } 56 catch (Exception e) 57 { 58 throw new IOException("exception decoding certificate structure: " + e.toString()); 59 } 60 } 61 62 public X509V2AttributeCertificate( 63 InputStream encIn) 64 throws IOException 65 { 66 this(getObject(encIn)); 67 } 68 69 public X509V2AttributeCertificate( 70 byte[] encoded) 71 throws IOException 72 { 73 this(new ByteArrayInputStream(encoded)); 74 } 75 76 X509V2AttributeCertificate( 77 AttributeCertificate cert) 78 throws IOException 79 { 80 this.cert = cert; 81 82 try 83 { 84 this.notAfter = cert.getAcinfo().getAttrCertValidityPeriod().getNotAfterTime().getDate(); 85 this.notBefore = cert.getAcinfo().getAttrCertValidityPeriod().getNotBeforeTime().getDate(); 86 } 87 catch (ParseException e) 88 { 89 throw new IOException("invalid data structure in certificate!"); 90 } 91 } 92 93 public int getVersion() 94 { 95 return cert.getAcinfo().getVersion().getValue().intValue() + 1; 96 } 97 98 public BigInteger getSerialNumber() 99 { 100 return cert.getAcinfo().getSerialNumber().getValue(); 101 } 102 103 public AttributeCertificateHolder getHolder() 104 { 105 return new AttributeCertificateHolder((ASN1Sequence)cert.getAcinfo().getHolder().toASN1Object()); 106 } 107 108 public AttributeCertificateIssuer getIssuer() 109 { 110 return new AttributeCertificateIssuer(cert.getAcinfo().getIssuer()); 111 } 112 113 public Date getNotBefore() 114 { 115 return notBefore; 116 } 117 118 public Date getNotAfter() 119 { 120 return notAfter; 121 } 122 123 public boolean[] getIssuerUniqueID() 124 { 125 DERBitString id = cert.getAcinfo().getIssuerUniqueID(); 126 127 if (id != null) 128 { 129 byte[] bytes = id.getBytes(); 130 boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()]; 131 132 for (int i = 0; i != boolId.length; i++) 133 { 134 boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; 135 } 136 137 return boolId; 138 } 139 140 return null; 141 } 142 143 public void checkValidity() 144 throws CertificateExpiredException, CertificateNotYetValidException 145 { 146 this.checkValidity(new Date()); 147 } 148 149 public void checkValidity( 150 Date date) 151 throws CertificateExpiredException, CertificateNotYetValidException 152 { 153 if (date.after(this.getNotAfter())) 154 { 155 throw new CertificateExpiredException("certificate expired on " + this.getNotAfter()); 156 } 157 158 if (date.before(this.getNotBefore())) 159 { 160 throw new CertificateNotYetValidException("certificate not valid till " + this.getNotBefore()); 161 } 162 } 163 164 public byte[] getSignature() 165 { 166 return cert.getSignatureValue().getBytes(); 167 } 168 169 public final void verify( 170 PublicKey key, 171 String provider) 172 throws CertificateException, NoSuchAlgorithmException, 173 InvalidKeyException, NoSuchProviderException, SignatureException 174 { 175 Signature signature = null; 176 177 if (!cert.getSignatureAlgorithm().equals(cert.getAcinfo().getSignature())) 178 { 179 throw new CertificateException("Signature algorithm in certificate info not same as outer certificate"); 180 } 181 182 signature = Signature.getInstance(cert.getSignatureAlgorithm().getObjectId().getId(), provider); 183 184 signature.initVerify(key); 185 186 try 187 { 188 signature.update(cert.getAcinfo().getEncoded()); 189 } 190 catch (IOException e) 191 { 192 throw new SignatureException("Exception encoding certificate info object"); 193 } 194 195 if (!signature.verify(this.getSignature())) 196 { 197 throw new InvalidKeyException("Public key presented not for certificate signature"); 198 } 199 } 200 201 public byte[] getEncoded() 202 throws IOException 203 { 204 return cert.getEncoded(); 205 } 206 207 public byte[] getExtensionValue(String oid) 208 { 209 X509Extensions extensions = cert.getAcinfo().getExtensions(); 210 211 if (extensions != null) 212 { 213 X509Extension ext = extensions.getExtension(new DERObjectIdentifier(oid)); 214 215 if (ext != null) 216 { 217 try 218 { 219 return ext.getValue().getEncoded(ASN1Encodable.DER); 220 } 221 catch (Exception e) 222 { 223 throw new RuntimeException("error encoding " + e.toString()); 224 } 225 } 226 } 227 228 return null; 229 } 230 231 private Set getExtensionOIDs( 232 boolean critical) 233 { 234 X509Extensions extensions = cert.getAcinfo().getExtensions(); 235 236 if (extensions != null) 237 { 238 Set set = new HashSet(); 239 Enumeration e = extensions.oids(); 240 241 while (e.hasMoreElements()) 242 { 243 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 244 X509Extension ext = extensions.getExtension(oid); 245 246 if (ext.isCritical() == critical) 247 { 248 set.add(oid.getId()); 249 } 250 } 251 252 return set; 253 } 254 255 return null; 256 } 257 258 public Set getNonCriticalExtensionOIDs() 259 { 260 return getExtensionOIDs(false); 261 } 262 263 public Set getCriticalExtensionOIDs() 264 { 265 return getExtensionOIDs(true); 266 } 267 268 public boolean hasUnsupportedCriticalExtension() 269 { 270 Set extensions = getCriticalExtensionOIDs(); 271 272 return extensions != null && !extensions.isEmpty(); 273 } 274 275 public X509Attribute[] getAttributes() 276 { 277 ASN1Sequence seq = cert.getAcinfo().getAttributes(); 278 X509Attribute[] attrs = new X509Attribute[seq.size()]; 279 280 for (int i = 0; i != seq.size(); i++) 281 { 282 attrs[i] = new X509Attribute((ASN1Encodable)seq.getObjectAt(i)); 283 } 284 285 return attrs; 286 } 287 288 public X509Attribute[] getAttributes(String oid) 289 { 290 ASN1Sequence seq = cert.getAcinfo().getAttributes(); 291 List list = new ArrayList(); 292 293 for (int i = 0; i != seq.size(); i++) 294 { 295 X509Attribute attr = new X509Attribute((ASN1Encodable)seq.getObjectAt(i)); 296 if (attr.getOID().equals(oid)) 297 { 298 list.add(attr); 299 } 300 } 301 302 if (list.size() == 0) 303 { 304 return null; 305 } 306 307 return (X509Attribute[])list.toArray(new X509Attribute[list.size()]); 308 } 309 310 public boolean equals( 311 Object o) 312 { 313 if (o == this) 314 { 315 return true; 316 } 317 318 if (!(o instanceof X509AttributeCertificate)) 319 { 320 return false; 321 } 322 323 X509AttributeCertificate other = (X509AttributeCertificate)o; 324 325 try 326 { 327 byte[] b1 = this.getEncoded(); 328 byte[] b2 = other.getEncoded(); 329 330 return Arrays.areEqual(b1, b2); 331 } 332 catch (IOException e) 333 { 334 return false; 335 } 336 } 337 338 public int hashCode() 339 { 340 try 341 { 342 return Arrays.hashCode(this.getEncoded()); 343 } 344 catch (IOException e) 345 { 346 return 0; 347 } 348 } 349 } 350