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