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