1 17 18 package org.apache.geronimo.util.jce.provider; 19 20 import java.io.ByteArrayInputStream ; 21 import java.io.ByteArrayOutputStream ; 22 import java.io.IOException ; 23 import java.math.BigInteger ; 24 import java.security.InvalidKeyException ; 25 import java.security.NoSuchAlgorithmException ; 26 import java.security.NoSuchProviderException ; 27 import java.security.Principal ; 28 import java.security.Provider ; 29 import java.security.PublicKey ; 30 import java.security.Security ; 31 import java.security.Signature ; 32 import java.security.SignatureException ; 33 import java.security.cert.CertificateEncodingException ; 34 import java.security.cert.CertificateException ; 35 import java.security.cert.CertificateExpiredException ; 36 import java.security.cert.CertificateNotYetValidException ; 37 import java.security.cert.CertificateParsingException ; 38 import java.security.cert.X509Certificate ; 39 import java.util.ArrayList ; 40 import java.util.Collections ; 41 import java.util.Date ; 42 import java.util.Enumeration ; 43 import java.util.HashSet ; 44 import java.util.Hashtable ; 45 import java.util.List ; 46 import java.util.Set ; 47 import java.util.Vector ; 48 49 import javax.security.auth.x500.X500Principal ; 50 51 import org.apache.geronimo.util.asn1.*; 52 import org.apache.geronimo.util.asn1.misc.MiscObjectIdentifiers; 53 import org.apache.geronimo.util.asn1.misc.NetscapeCertType; 54 import org.apache.geronimo.util.asn1.misc.NetscapeRevocationURL; 55 import org.apache.geronimo.util.asn1.misc.VerisignCzagExtension; 56 import org.apache.geronimo.util.asn1.util.ASN1Dump; 57 import org.apache.geronimo.util.asn1.x509.BasicConstraints; 58 import org.apache.geronimo.util.asn1.x509.KeyUsage; 59 import org.apache.geronimo.util.asn1.x509.X509CertificateStructure; 60 import org.apache.geronimo.util.asn1.x509.X509Extension; 61 import org.apache.geronimo.util.asn1.x509.X509Extensions; 62 import org.apache.geronimo.util.jce.X509Principal; 63 import org.apache.geronimo.util.jce.interfaces.PKCS12BagAttributeCarrier; 64 import org.apache.geronimo.util.encoders.Hex; 65 66 public class X509CertificateObject 67 extends X509Certificate 68 implements PKCS12BagAttributeCarrier 69 { 70 private X509CertificateStructure c; 71 private Hashtable pkcs12Attributes = new Hashtable (); 72 private Vector pkcs12Ordering = new Vector (); 73 74 public X509CertificateObject( 75 X509CertificateStructure c) 76 { 77 this.c = c; 78 } 79 80 public void checkValidity() 81 throws CertificateExpiredException , CertificateNotYetValidException 82 { 83 this.checkValidity(new Date ()); 84 } 85 86 public void checkValidity( 87 Date date) 88 throws CertificateExpiredException , CertificateNotYetValidException 89 { 90 if (date.after(this.getNotAfter())) 91 { 92 throw new CertificateExpiredException ("certificate expired on " + c.getEndDate().getTime()); 93 } 94 95 if (date.before(this.getNotBefore())) 96 { 97 throw new CertificateNotYetValidException ("certificate not valid till " + c.getStartDate().getTime()); 98 } 99 } 100 101 public int getVersion() 102 { 103 return c.getVersion(); 104 } 105 106 public BigInteger getSerialNumber() 107 { 108 return c.getSerialNumber().getValue(); 109 } 110 111 public Principal getIssuerDN() 112 { 113 return new X509Principal(c.getIssuer()); 114 } 115 116 public X500Principal getIssuerX500Principal() 117 { 118 try 119 { 120 ByteArrayOutputStream bOut = new ByteArrayOutputStream (); 121 ASN1OutputStream aOut = new ASN1OutputStream(bOut); 122 123 aOut.writeObject(c.getIssuer()); 124 125 return new X500Principal (bOut.toByteArray()); 126 } 127 catch (IOException e) 128 { 129 throw new IllegalStateException ("can't encode issuer DN"); 130 } 131 } 132 133 public Principal getSubjectDN() 134 { 135 return new X509Principal(c.getSubject()); 136 } 137 138 public X500Principal getSubjectX500Principal() 139 { 140 try 141 { 142 ByteArrayOutputStream bOut = new ByteArrayOutputStream (); 143 ASN1OutputStream aOut = new ASN1OutputStream(bOut); 144 145 aOut.writeObject(c.getSubject()); 146 147 return new X500Principal (bOut.toByteArray()); 148 } 149 catch (IOException e) 150 { 151 throw new IllegalStateException ("can't encode issuer DN"); 152 } 153 } 154 155 public Date getNotBefore() 156 { 157 return c.getStartDate().getDate(); 158 } 159 160 public Date getNotAfter() 161 { 162 return c.getEndDate().getDate(); 163 } 164 165 public byte[] getTBSCertificate() 166 throws CertificateEncodingException 167 { 168 ByteArrayOutputStream bOut = new ByteArrayOutputStream (); 169 DEROutputStream dOut = new DEROutputStream(bOut); 170 171 try 172 { 173 dOut.writeObject(c.getTBSCertificate()); 174 175 return bOut.toByteArray(); 176 } 177 catch (IOException e) 178 { 179 throw new CertificateEncodingException (e.toString()); 180 } 181 } 182 183 public byte[] getSignature() 184 { 185 return c.getSignature().getBytes(); 186 } 187 188 192 public String getSigAlgName() 193 { 194 Provider [] provs = Security.getProviders(); 195 196 for (int i = 0; i != provs.length; i++) 200 { 201 String algName = provs[i].getProperty("Alg.Alias.Signature." + this.getSigAlgOID()); 202 if (algName != null) 203 { 204 return algName; 205 } 206 } 207 208 return this.getSigAlgOID(); 209 } 210 211 214 public String getSigAlgOID() 215 { 216 return c.getSignatureAlgorithm().getObjectId().getId(); 217 } 218 219 222 public byte[] getSigAlgParams() 223 { 224 ByteArrayOutputStream bOut = new ByteArrayOutputStream (); 225 226 if (c.getSignatureAlgorithm().getParameters() != null) 227 { 228 try 229 { 230 DEROutputStream dOut = new DEROutputStream(bOut); 231 232 dOut.writeObject(c.getSignatureAlgorithm().getParameters()); 233 } 234 catch (Exception e) 235 { 236 throw new RuntimeException ("exception getting sig parameters " + e); 237 } 238 239 return bOut.toByteArray(); 240 } 241 else 242 { 243 return null; 244 } 245 } 246 247 public boolean[] getIssuerUniqueID() 248 { 249 DERBitString id = c.getTBSCertificate().getIssuerUniqueId(); 250 251 if (id != null) 252 { 253 byte[] bytes = id.getBytes(); 254 boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()]; 255 256 for (int i = 0; i != boolId.length; i++) 257 { 258 boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; 259 } 260 261 return boolId; 262 } 263 264 return null; 265 } 266 267 public boolean[] getSubjectUniqueID() 268 { 269 DERBitString id = c.getTBSCertificate().getSubjectUniqueId(); 270 271 if (id != null) 272 { 273 byte[] bytes = id.getBytes(); 274 boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()]; 275 276 for (int i = 0; i != boolId.length; i++) 277 { 278 boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; 279 } 280 281 return boolId; 282 } 283 284 return null; 285 } 286 287 public boolean[] getKeyUsage() 288 { 289 byte[] bytes = this.getExtensionBytes("2.5.29.15"); 290 int length = 0; 291 292 if (bytes != null) 293 { 294 try 295 { 296 ASN1InputStream dIn = new ASN1InputStream(new ByteArrayInputStream (bytes)); 297 DERBitString bits = (DERBitString)dIn.readObject(); 298 299 bytes = bits.getBytes(); 300 length = (bytes.length * 8) - bits.getPadBits(); 301 } 302 catch (Exception e) 303 { 304 throw new RuntimeException ("error processing key usage extension"); 305 } 306 307 boolean[] keyUsage = new boolean[(length < 9) ? 9 : length]; 308 309 for (int i = 0; i != length; i++) 310 { 311 keyUsage[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0; 312 } 313 314 return keyUsage; 315 } 316 317 return null; 318 } 319 320 public List getExtendedKeyUsage() 321 throws CertificateParsingException 322 { 323 byte[] bytes = this.getExtensionBytes("2.5.29.37"); 324 int length = 0; 325 326 if (bytes != null) 327 { 328 try 329 { 330 ASN1InputStream dIn = new ASN1InputStream(new ByteArrayInputStream (bytes)); 331 ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); 332 ArrayList list = new ArrayList (); 333 334 for (int i = 0; i != seq.size(); i++) 335 { 336 list.add(((DERObjectIdentifier)seq.getObjectAt(i)).getId()); 337 } 338 339 return Collections.unmodifiableList(list); 340 } 341 catch (Exception e) 342 { 343 throw new CertificateParsingException ("error processing extended key usage extension"); 344 } 345 } 346 347 return null; 348 } 349 350 public int getBasicConstraints() 351 { 352 byte[] bytes = this.getExtensionBytes("2.5.29.19"); 353 354 if (bytes != null) 355 { 356 try 357 { 358 ASN1InputStream dIn = new ASN1InputStream(new ByteArrayInputStream (bytes)); 359 ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); 360 361 if (seq.size() == 2) 362 { 363 if (((DERBoolean)seq.getObjectAt(0)).isTrue()) 364 { 365 return ((DERInteger)seq.getObjectAt(1)).getValue().intValue(); 366 } 367 else 368 { 369 return -1; 370 } 371 } 372 else if (seq.size() == 1) 373 { 374 if (seq.getObjectAt(0) instanceof DERBoolean) 375 { 376 if (((DERBoolean)seq.getObjectAt(0)).isTrue()) 377 { 378 return Integer.MAX_VALUE; 379 } 380 else 381 { 382 return -1; 383 } 384 } 385 else 386 { 387 return -1; 388 } 389 } 390 } 391 catch (Exception e) 392 { 393 throw new RuntimeException ("error processing key usage extension"); 394 } 395 } 396 397 return -1; 398 } 399 400 public Set getCriticalExtensionOIDs() 401 { 402 if (this.getVersion() == 3) 403 { 404 HashSet set = new HashSet (); 405 X509Extensions extensions = c.getTBSCertificate().getExtensions(); 406 407 if (extensions != null) 408 { 409 Enumeration e = extensions.oids(); 410 411 while (e.hasMoreElements()) 412 { 413 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 414 X509Extension ext = extensions.getExtension(oid); 415 416 if (ext.isCritical()) 417 { 418 set.add(oid.getId()); 419 } 420 } 421 422 return set; 423 } 424 } 425 426 return null; 427 } 428 429 private byte[] getExtensionBytes(String oid) 430 { 431 X509Extensions exts = c.getTBSCertificate().getExtensions(); 432 433 if (exts != null) 434 { 435 X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); 436 if (ext != null) 437 { 438 return ext.getValue().getOctets(); 439 } 440 } 441 442 return null; 443 } 444 445 public byte[] getExtensionValue(String oid) 446 { 447 X509Extensions exts = c.getTBSCertificate().getExtensions(); 448 449 if (exts != null) 450 { 451 X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); 452 453 if (ext != null) 454 { 455 ByteArrayOutputStream bOut = new ByteArrayOutputStream (); 456 DEROutputStream dOut = new DEROutputStream(bOut); 457 458 try 459 { 460 dOut.writeObject(ext.getValue()); 461 462 return bOut.toByteArray(); 463 } 464 catch (Exception e) 465 { 466 throw new RuntimeException ("error encoding " + e.toString()); 467 } 468 } 469 } 470 471 return null; 472 } 473 474 public Set getNonCriticalExtensionOIDs() 475 { 476 if (this.getVersion() == 3) 477 { 478 HashSet set = new HashSet (); 479 X509Extensions extensions = c.getTBSCertificate().getExtensions(); 480 481 if (extensions != null) 482 { 483 Enumeration e = extensions.oids(); 484 485 while (e.hasMoreElements()) 486 { 487 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 488 X509Extension ext = extensions.getExtension(oid); 489 490 if (!ext.isCritical()) 491 { 492 set.add(oid.getId()); 493 } 494 } 495 496 return set; 497 } 498 } 499 500 return null; 501 } 502 503 public boolean hasUnsupportedCriticalExtension() 504 { 505 if (this.getVersion() == 3) 506 { 507 X509Extensions extensions = c.getTBSCertificate().getExtensions(); 508 509 if (extensions != null) 510 { 511 Enumeration e = extensions.oids(); 512 513 while (e.hasMoreElements()) 514 { 515 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 516 if (oid.getId().equals("2.5.29.15") 517 || oid.getId().equals("2.5.29.19")) 518 { 519 continue; 520 } 521 522 X509Extension ext = extensions.getExtension(oid); 523 524 if (ext.isCritical()) 525 { 526 return true; 527 } 528 } 529 } 530 } 531 532 return false; 533 } 534 535 public PublicKey getPublicKey() 536 { 537 return JDKKeyFactory.createPublicKeyFromPublicKeyInfo(c.getSubjectPublicKeyInfo()); 538 } 539 540 public byte[] getEncoded() 541 throws CertificateEncodingException 542 { 543 ByteArrayOutputStream bOut = new ByteArrayOutputStream (); 544 DEROutputStream dOut = new DEROutputStream(bOut); 545 546 try 547 { 548 dOut.writeObject(c); 549 550 return bOut.toByteArray(); 551 } 552 catch (IOException e) 553 { 554 throw new CertificateEncodingException (e.toString()); 555 } 556 } 557 558 public void setBagAttribute( 559 DERObjectIdentifier oid, 560 DEREncodable attribute) 561 { 562 pkcs12Attributes.put(oid, attribute); 563 pkcs12Ordering.addElement(oid); 564 } 565 566 public DEREncodable getBagAttribute( 567 DERObjectIdentifier oid) 568 { 569 return (DEREncodable)pkcs12Attributes.get(oid); 570 } 571 572 public Enumeration getBagAttributeKeys() 573 { 574 return pkcs12Ordering.elements(); 575 } 576 577 public String toString() 578 { 579 StringBuffer buf = new StringBuffer (); 580 String nl = System.getProperty("line.separator"); 581 582 buf.append(" [0] Version: " + this.getVersion() + nl); 583 buf.append(" SerialNumber: " + this.getSerialNumber() + nl); 584 buf.append(" IssuerDN: " + this.getIssuerDN() + nl); 585 buf.append(" Start Date: " + this.getNotBefore() + nl); 586 buf.append(" Final Date: " + this.getNotAfter() + nl); 587 buf.append(" SubjectDN: " + this.getSubjectDN() + nl); 588 buf.append(" Public Key: " + this.getPublicKey() + nl); 589 buf.append(" Signature Algorithm: " + this.getSigAlgName() + nl); 590 591 byte[] sig = this.getSignature(); 592 593 buf.append(" Signature: " + new String (Hex.encode(sig, 0, 20)) + nl); 594 for (int i = 20; i < sig.length; i += 20) 595 { 596 if (i < sig.length - 20) 597 { 598 buf.append(" " + new String (Hex.encode(sig, i, 20)) + nl); 599 } 600 else 601 { 602 buf.append(" " + new String (Hex.encode(sig, i, sig.length - i)) + nl); 603 } 604 } 605 606 X509Extensions extensions = c.getTBSCertificate().getExtensions(); 607 608 if (extensions != null) 609 { 610 Enumeration e = extensions.oids(); 611 612 if (e.hasMoreElements()) 613 { 614 buf.append(" Extensions: \n"); 615 } 616 617 while (e.hasMoreElements()) 618 { 619 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); 620 X509Extension ext = extensions.getExtension(oid); 621 622 if (ext.getValue() != null) 623 { 624 byte[] octs = ext.getValue().getOctets(); 625 ByteArrayInputStream bIn = new ByteArrayInputStream (octs); 626 ASN1InputStream dIn = new ASN1InputStream(bIn); 627 buf.append(" critical(" + ext.isCritical() + ") "); 628 try 629 { 630 if (oid.equals(X509Extensions.BasicConstraints)) 631 { 632 buf.append(new BasicConstraints((ASN1Sequence)dIn.readObject()) + nl); 633 } 634 else if (oid.equals(X509Extensions.KeyUsage)) 635 { 636 buf.append(new KeyUsage((DERBitString)dIn.readObject()) + nl); 637 } 638 else if (oid.equals(MiscObjectIdentifiers.netscapeCertType)) 639 { 640 buf.append(new NetscapeCertType((DERBitString)dIn.readObject()) + nl); 641 } 642 else if (oid.equals(MiscObjectIdentifiers.netscapeRevocationURL)) 643 { 644 buf.append(new NetscapeRevocationURL((DERIA5String)dIn.readObject()) + nl); 645 } 646 else if (oid.equals(MiscObjectIdentifiers.verisignCzagExtension)) 647 { 648 buf.append(new VerisignCzagExtension((DERIA5String)dIn.readObject()) + nl); 649 } 650 else 651 { 652 buf.append(oid.getId()); 653 buf.append(" value = " + ASN1Dump.dumpAsString(dIn.readObject()) + nl); 654 } 656 } 657 catch (Exception ex) 658 { 659 buf.append(oid.getId()); 660 buf.append(" value = " + "*****" + nl); 662 } 663 } 664 else 665 { 666 buf.append(nl); 667 } 668 } 669 } 670 671 return buf.toString(); 672 } 673 674 public final void verify( 675 PublicKey key) 676 throws CertificateException , NoSuchAlgorithmException , 677 InvalidKeyException , NoSuchProviderException , SignatureException 678 { 679 Signature signature = null; 680 681 if (!c.getSignatureAlgorithm().equals(c.getTBSCertificate().getSignature())) 682 { 683 throw new CertificateException ("signature algorithm in TBS cert not same as outer cert"); 684 } 685 686 try 687 { 688 signature = Signature.getInstance(c.getSignatureAlgorithm().getObjectId().getId(), "BC"); 689 } 690 catch (Exception e) 691 { 692 signature = Signature.getInstance(c.getSignatureAlgorithm().getObjectId().getId()); 693 } 694 695 signature.initVerify(key); 696 697 signature.update(this.getTBSCertificate()); 698 699 if (!signature.verify(this.getSignature())) 700 { 701 throw new InvalidKeyException ("Public key presented not for certificate signature"); 702 } 703 } 704 705 public final void verify( 706 PublicKey key, 707 String sigProvider) 708 throws CertificateException , NoSuchAlgorithmException , 709 InvalidKeyException , NoSuchProviderException , SignatureException 710 { 711 Signature signature = Signature.getInstance(c.getSignatureAlgorithm().getObjectId().getId(), sigProvider); 712 713 if (!c.getSignatureAlgorithm().equals(c.getTBSCertificate().getSignature())) 714 { 715 throw new CertificateException ("signature algorithm in TBS cert not same as outer cert"); 716 } 717 718 signature.initVerify(key); 719 720 signature.update(this.getTBSCertificate()); 721 722 if (!signature.verify(this.getSignature())) 723 { 724 throw new InvalidKeyException ("Public key presented not for certificate signature"); 725 } 726 } 727 } 728 | Popular Tags |