AttributeCertificateHolder.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
1package org.bouncycastle.x509; 2 3import java.io.IOException; 4import java.math.BigInteger; 5import java.security.MessageDigest; 6import java.security.Principal; 7import java.security.cert.CertSelector; 8import java.security.cert.Certificate; 9import java.security.cert.CertificateEncodingException; 10import java.security.cert.CertificateParsingException; 11import java.security.cert.X509Certificate; 12import java.util.ArrayList; 13import java.util.List; 14 15import javax.security.auth.x500.X500Principal; 16 17import org.bouncycastle.asn1.ASN1Encodable; 18import org.bouncycastle.asn1.ASN1Integer; 19import org.bouncycastle.asn1.ASN1ObjectIdentifier; 20import org.bouncycastle.asn1.ASN1Sequence; 21import org.bouncycastle.asn1.DERSequence; 22import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 23import org.bouncycastle.asn1.x509.GeneralName; 24import org.bouncycastle.asn1.x509.GeneralNames; 25import org.bouncycastle.asn1.x509.Holder; 26import org.bouncycastle.asn1.x509.IssuerSerial; 27import org.bouncycastle.asn1.x509.ObjectDigestInfo; 28import org.bouncycastle.jce.PrincipalUtil; 29import org.bouncycastle.jce.X509Principal; 30import org.bouncycastle.util.Arrays; 31import org.bouncycastle.util.Selector; 32 33/** 34 * The Holder object. 35 * 36 * <pre> 37 * Holder ::= SEQUENCE { 38 * baseCertificateID [0] IssuerSerial OPTIONAL, 39 * -- the issuer and serial number of 40 * -- the holder's Public Key Certificate 41 * entityName [1] GeneralNames OPTIONAL, 42 * -- the name of the claimant or role 43 * objectDigestInfo [2] ObjectDigestInfo OPTIONAL 44 * -- used to directly authenticate the holder, 45 * -- for example, an executable 46 * } 47 * </pre> 48 * @deprecated use org.bouncycastle.cert.AttributeCertificateHolder 49 */ 50public class AttributeCertificateHolder 51 implements CertSelector, Selector 52{ 53 final Holder holder; 54 55 AttributeCertificateHolder(ASN1Sequence seq) 56 { 57 holder = Holder.getInstance(seq); 58 } 59 60 public AttributeCertificateHolder(X509Principal issuerName, 61 BigInteger serialNumber) 62 { 63 holder = new org.bouncycastle.asn1.x509.Holder(new IssuerSerial( 64 GeneralNames.getInstance(new DERSequence(new GeneralName(issuerName))), 65 new ASN1Integer(serialNumber))); 66 } 67 68 public AttributeCertificateHolder(X500Principal issuerName, 69 BigInteger serialNumber) 70 { 71 this(X509Util.convertPrincipal(issuerName), serialNumber); 72 } 73 74 public AttributeCertificateHolder(X509Certificate cert) 75 throws CertificateParsingException 76 { 77 X509Principal name; 78 79 try 80 { 81 name = PrincipalUtil.getIssuerX509Principal(cert); 82 } 83 catch (Exception e) 84 { 85 throw new CertificateParsingException(e.getMessage()); 86 } 87 88 holder = new Holder(new IssuerSerial(generateGeneralNames(name), 89 new ASN1Integer(cert.getSerialNumber()))); 90 } 91 92 public AttributeCertificateHolder(X509Principal principal) 93 { 94 holder = new Holder(generateGeneralNames(principal)); 95 } 96 97 public AttributeCertificateHolder(X500Principal principal) 98 { 99 this(X509Util.convertPrincipal(principal)); 100 } 101 102 /** 103 * Constructs a holder for v2 attribute certificates with a hash value for 104 * some type of object. 105 * <p> 106 * <code>digestedObjectType</code> can be one of the following: 107 * <ul> 108 * <li>0 - publicKey - A hash of the public key of the holder must be 109 * passed. 110 * <li>1 - publicKeyCert - A hash of the public key certificate of the 111 * holder must be passed. 112 * <li>2 - otherObjectDigest - A hash of some other object type must be 113 * passed. <code>otherObjectTypeID</code> must not be empty. 114 * </ul> 115 * <p> 116 * This cannot be used if a v1 attribute certificate is used. 117 * 118 * @param digestedObjectType The digest object type. 119 * @param digestAlgorithm The algorithm identifier for the hash. 120 * @param otherObjectTypeID The object type ID if 121 * <code>digestedObjectType</code> is 122 * <code>otherObjectDigest</code>. 123 * @param objectDigest The hash value. 124 */ 125 public AttributeCertificateHolder(int digestedObjectType, 126 String digestAlgorithm, String otherObjectTypeID, byte[] objectDigest) 127 { 128 holder = new Holder(new ObjectDigestInfo(digestedObjectType, 129 new ASN1ObjectIdentifier(otherObjectTypeID), new AlgorithmIdentifier(digestAlgorithm), Arrays 130 .clone(objectDigest))); 131 } 132 133 /** 134 * Returns the digest object type if an object digest info is used. 135 * <p> 136 * <ul> 137 * <li>0 - publicKey - A hash of the public key of the holder must be 138 * passed. 139 * <li>1 - publicKeyCert - A hash of the public key certificate of the 140 * holder must be passed. 141 * <li>2 - otherObjectDigest - A hash of some other object type must be 142 * passed. <code>otherObjectTypeID</code> must not be empty. 143 * </ul> 144 * 145 * @return The digest object type or -1 if no object digest info is set. 146 */ 147 public int getDigestedObjectType() 148 { 149 if (holder.getObjectDigestInfo() != null) 150 { 151 return holder.getObjectDigestInfo().getDigestedObjectType() 152 .getValue().intValue(); 153 } 154 return -1; 155 } 156 157 /** 158 * Returns the other object type ID if an object digest info is used. 159 * 160 * @return The other object type ID or <code>null</code> if no object 161 * digest info is set. 162 */ 163 public String getDigestAlgorithm() 164 { 165 if (holder.getObjectDigestInfo() != null) 166 { 167 return holder.getObjectDigestInfo().getDigestAlgorithm().getObjectId() 168 .getId(); 169 } 170 return null; 171 } 172 173 /** 174 * Returns the hash if an object digest info is used. 175 * 176 * @return The hash or <code>null</code> if no object digest info is set. 177 */ 178 public byte[] getObjectDigest() 179 { 180 if (holder.getObjectDigestInfo() != null) 181 { 182 return holder.getObjectDigestInfo().getObjectDigest().getBytes(); 183 } 184 return null; 185 } 186 187 /** 188 * Returns the digest algorithm ID if an object digest info is used. 189 * 190 * @return The digest algorithm ID or <code>null</code> if no object 191 * digest info is set. 192 */ 193 public String getOtherObjectTypeID() 194 { 195 if (holder.getObjectDigestInfo() != null) 196 { 197 holder.getObjectDigestInfo().getOtherObjectTypeID().getId(); 198 } 199 return null; 200 } 201 202 private GeneralNames generateGeneralNames(X509Principal principal) 203 { 204 return GeneralNames.getInstance(new DERSequence(new GeneralName(principal))); 205 } 206 207 private boolean matchesDN(X509Principal subject, GeneralNames targets) 208 { 209 GeneralName[] names = targets.getNames(); 210 211 for (int i = 0; i != names.length; i++) 212 { 213 GeneralName gn = names[i]; 214 215 if (gn.getTagNo() == GeneralName.directoryName) 216 { 217 try 218 { 219 if (new X509Principal(((ASN1Encodable)gn.getName()).toASN1Primitive() 220 .getEncoded()).equals(subject)) 221 { 222 return true; 223 } 224 } 225 catch (IOException e) 226 { 227 } 228 } 229 } 230 231 return false; 232 } 233 234 private Object[] getNames(GeneralName[] names) 235 { 236 List l = new ArrayList(names.length); 237 238 for (int i = 0; i != names.length; i++) 239 { 240 if (names[i].getTagNo() == GeneralName.directoryName) 241 { 242 try 243 { 244 l.add(new X500Principal( 245 ((ASN1Encodable)names[i].getName()).toASN1Primitive().getEncoded())); 246 } 247 catch (IOException e) 248 { 249 throw new RuntimeException("badly formed Name object"); 250 } 251 } 252 } 253 254 return l.toArray(new Object[l.size()]); 255 } 256 257 private Principal[] getPrincipals(GeneralNames names) 258 { 259 Object[] p = this.getNames(names.getNames()); 260 List l = new ArrayList(); 261 262 for (int i = 0; i != p.length; i++) 263 { 264 if (p[i] instanceof Principal) 265 { 266 l.add(p[i]); 267 } 268 } 269 270 return (Principal[])l.toArray(new Principal[l.size()]); 271 } 272 273 /** 274 * Return any principal objects inside the attribute certificate holder 275 * entity names field. 276 * 277 * @return an array of Principal objects (usually X500Principal), null if no 278 * entity names field is set. 279 */ 280 public Principal[] getEntityNames() 281 { 282 if (holder.getEntityName() != null) 283 { 284 return getPrincipals(holder.getEntityName()); 285 } 286 287 return null; 288 } 289 290 /** 291 * Return the principals associated with the issuer attached to this holder 292 * 293 * @return an array of principals, null if no BaseCertificateID is set. 294 */ 295 public Principal[] getIssuer() 296 { 297 if (holder.getBaseCertificateID() != null) 298 { 299 return getPrincipals(holder.getBaseCertificateID().getIssuer()); 300 } 301 302 return null; 303 } 304 305 /** 306 * Return the serial number associated with the issuer attached to this 307 * holder. 308 * 309 * @return the certificate serial number, null if no BaseCertificateID is 310 * set. 311 */ 312 public BigInteger getSerialNumber() 313 { 314 if (holder.getBaseCertificateID() != null) 315 { 316 return holder.getBaseCertificateID().getSerial().getValue(); 317 } 318 319 return null; 320 } 321 322 public Object clone() 323 { 324 return new AttributeCertificateHolder((ASN1Sequence)holder 325 .toASN1Object()); 326 } 327 328 public boolean match(Certificate cert) 329 { 330 if (!(cert instanceof X509Certificate)) 331 { 332 return false; 333 } 334 335 X509Certificate x509Cert = (X509Certificate)cert; 336 337 try 338 { 339 if (holder.getBaseCertificateID() != null) 340 { 341 return holder.getBaseCertificateID().getSerial().getValue().equals(x509Cert.getSerialNumber()) 342 && matchesDN(PrincipalUtil.getIssuerX509Principal(x509Cert), holder.getBaseCertificateID().getIssuer()); 343 } 344 345 if (holder.getEntityName() != null) 346 { 347 if (matchesDN(PrincipalUtil.getSubjectX509Principal(x509Cert), 348 holder.getEntityName())) 349 { 350 return true; 351 } 352 } 353 if (holder.getObjectDigestInfo() != null) 354 { 355 MessageDigest md = null; 356 try 357 { 358 md = MessageDigest.getInstance(getDigestAlgorithm(), "BC"); 359 360 } 361 catch (Exception e) 362 { 363 return false; 364 } 365 switch (getDigestedObjectType()) 366 { 367 case ObjectDigestInfo.publicKey: 368 // TODO: DSA Dss-parms 369 md.update(cert.getPublicKey().getEncoded()); 370 break; 371 case ObjectDigestInfo.publicKeyCert: 372 md.update(cert.getEncoded()); 373 break; 374 } 375 if (!Arrays.areEqual(md.digest(), getObjectDigest())) 376 { 377 return false; 378 } 379 } 380 } 381 catch (CertificateEncodingException e) 382 { 383 return false; 384 } 385 386 return false; 387 } 388 389 public boolean equals(Object obj) 390 { 391 if (obj == this) 392 { 393 return true; 394 } 395 396 if (!(obj instanceof AttributeCertificateHolder)) 397 { 398 return false; 399 } 400 401 AttributeCertificateHolder other = (AttributeCertificateHolder)obj; 402 403 return this.holder.equals(other.holder); 404 } 405 406 public int hashCode() 407 { 408 return this.holder.hashCode(); 409 } 410 411 public boolean match(Object obj) 412 { 413 if (!(obj instanceof X509Certificate)) 414 { 415 return false; 416 } 417 418 return match((Certificate)obj); 419 } 420} 421