Source for gnu.java.security.x509.X509Certificate

   1: /* X509Certificate.java -- X.509 certificate.
   2:    Copyright (C) 2003, 2004  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.java.security.x509;
  40: 
  41: import gnu.classpath.debug.Component;
  42: import gnu.classpath.debug.SystemLogger;
  43: import gnu.java.security.OID;
  44: import gnu.java.security.der.BitString;
  45: import gnu.java.security.der.DER;
  46: import gnu.java.security.der.DERReader;
  47: import gnu.java.security.der.DERValue;
  48: import gnu.java.security.x509.ext.BasicConstraints;
  49: import gnu.java.security.x509.ext.ExtendedKeyUsage;
  50: import gnu.java.security.x509.ext.Extension;
  51: import gnu.java.security.x509.ext.IssuerAlternativeNames;
  52: import gnu.java.security.x509.ext.KeyUsage;
  53: import gnu.java.security.x509.ext.SubjectAlternativeNames;
  54: 
  55: import java.io.IOException;
  56: import java.io.InputStream;
  57: import java.io.PrintWriter;
  58: import java.io.Serializable;
  59: import java.io.StringWriter;
  60: import java.math.BigInteger;
  61: import java.security.AlgorithmParameters;
  62: import java.security.InvalidKeyException;
  63: import java.security.KeyFactory;
  64: import java.security.NoSuchAlgorithmException;
  65: import java.security.NoSuchProviderException;
  66: import java.security.Principal;
  67: import java.security.PublicKey;
  68: import java.security.Signature;
  69: import java.security.SignatureException;
  70: import java.security.cert.CertificateEncodingException;
  71: import java.security.cert.CertificateException;
  72: import java.security.cert.CertificateExpiredException;
  73: import java.security.cert.CertificateNotYetValidException;
  74: import java.security.cert.CertificateParsingException;
  75: import java.security.interfaces.DSAParams;
  76: import java.security.interfaces.DSAPublicKey;
  77: import java.security.spec.DSAParameterSpec;
  78: import java.security.spec.X509EncodedKeySpec;
  79: import java.util.ArrayList;
  80: import java.util.Arrays;
  81: import java.util.Collection;
  82: import java.util.Collections;
  83: import java.util.Date;
  84: import java.util.HashMap;
  85: import java.util.HashSet;
  86: import java.util.Iterator;
  87: import java.util.List;
  88: import java.util.Map;
  89: import java.util.Set;
  90: import java.util.logging.Logger;
  91: 
  92: import javax.security.auth.x500.X500Principal;
  93: 
  94: /**
  95:  * An implementation of X.509 certificates.
  96:  *
  97:  * @author Casey Marshall (rsdio@metastatic.org)
  98:  */
  99: public class X509Certificate extends java.security.cert.X509Certificate
 100:   implements Serializable, GnuPKIExtension
 101: {
 102: 
 103:   // Constants and fields.
 104:   // ------------------------------------------------------------------------
 105: 
 106:   private static final Logger logger = SystemLogger.SYSTEM;
 107: 
 108:   protected static final OID ID_DSA = new OID ("1.2.840.10040.4.1");
 109:   protected static final OID ID_DSA_WITH_SHA1 = new OID ("1.2.840.10040.4.3");
 110:   protected static final OID ID_RSA = new OID ("1.2.840.113549.1.1.1");
 111:   protected static final OID ID_RSA_WITH_MD2 = new OID ("1.2.840.113549.1.1.2");
 112:   protected static final OID ID_RSA_WITH_MD5 = new OID ("1.2.840.113549.1.1.4");
 113:   protected static final OID ID_RSA_WITH_SHA1 = new OID ("1.2.840.113549.1.1.5");
 114:   protected static final OID ID_ECDSA_WITH_SHA1 = new OID ("1.2.840.10045.4.1");
 115: 
 116:   // This object SHOULD be serialized with an instance of
 117:   // java.security.cert.Certificate.CertificateRep, thus all fields are
 118:   // transient.
 119: 
 120:   // The encoded certificate.
 121:   protected transient byte[] encoded;
 122: 
 123:   // TBSCertificate part.
 124:   protected transient byte[] tbsCertBytes;
 125:   protected transient int version;
 126:   protected transient BigInteger serialNo;
 127:   protected transient OID algId;
 128:   protected transient byte[] algVal;
 129:   protected transient X500DistinguishedName issuer;
 130:   protected transient Date notBefore;
 131:   protected transient Date notAfter;
 132:   protected transient X500DistinguishedName subject;
 133:   protected transient PublicKey subjectKey;
 134:   protected transient BitString issuerUniqueId;
 135:   protected transient BitString subjectUniqueId;
 136:   protected transient Map extensions;
 137: 
 138:   // Signature.
 139:   protected transient OID sigAlgId;
 140:   protected transient byte[] sigAlgVal;
 141:   protected transient byte[] signature;
 142: 
 143:   // Constructors.
 144:   // ------------------------------------------------------------------------
 145: 
 146:   /**
 147:    * Create a new X.509 certificate from the encoded data. The input
 148:    * data are expected to be the ASN.1 DER encoding of the certificate.
 149:    *
 150:    * @param encoded The encoded certificate data.
 151:    * @throws IOException If the certificate cannot be read, possibly
 152:    * from a formatting error.
 153:    * @throws CertificateException If the data read is not an X.509
 154:    * certificate.
 155:    */
 156:   public X509Certificate(InputStream encoded)
 157:     throws CertificateException, IOException
 158:   {
 159:     super();
 160:     extensions = new HashMap();
 161:     try
 162:       {
 163:         parse(encoded);
 164:       }
 165:     catch (IOException ioe)
 166:       {
 167:         logger.log (Component.X509, "", ioe);
 168:         throw ioe;
 169:       }
 170:     catch (Exception e)
 171:       {
 172:         logger.log (Component.X509, "", e);
 173:         CertificateException ce = new CertificateException(e.getMessage());
 174:         ce.initCause (e);
 175:         throw ce;
 176:       }
 177:   }
 178: 
 179:   protected X509Certificate()
 180:   {
 181:     extensions = new HashMap();
 182:   }
 183: 
 184:   // X509Certificate methods.
 185:   // ------------------------------------------------------------------------
 186: 
 187:   public void checkValidity()
 188:     throws CertificateExpiredException, CertificateNotYetValidException
 189:   {
 190:     checkValidity(new Date());
 191:   }
 192: 
 193:   public void checkValidity(Date date)
 194:     throws CertificateExpiredException, CertificateNotYetValidException
 195:   {
 196:     if (date.compareTo(notBefore) < 0)
 197:       {
 198:         throw new CertificateNotYetValidException();
 199:       }
 200:     if (date.compareTo(notAfter) > 0)
 201:       {
 202:         throw new CertificateExpiredException();
 203:       }
 204:   }
 205: 
 206:   public int getVersion()
 207:   {
 208:     return version;
 209:   }
 210: 
 211:   public BigInteger getSerialNumber()
 212:   {
 213:     return serialNo;
 214:   }
 215: 
 216:   public Principal getIssuerDN()
 217:   {
 218:     return issuer;
 219:   }
 220: 
 221:   public X500Principal getIssuerX500Principal()
 222:   {
 223:     return new X500Principal(issuer.getDer());
 224:   }
 225: 
 226:   public Principal getSubjectDN()
 227:   {
 228:     return subject;
 229:   }
 230: 
 231:   public X500Principal getSubjectX500Principal()
 232:   {
 233:     return new X500Principal(subject.getDer());
 234:   }
 235: 
 236:   public Date getNotBefore()
 237:   {
 238:     return (Date) notBefore.clone();
 239:   }
 240: 
 241:   public Date getNotAfter()
 242:   {
 243:     return (Date) notAfter.clone();
 244:   }
 245: 
 246:   public byte[] getTBSCertificate() throws CertificateEncodingException
 247:   {
 248:     return (byte[]) tbsCertBytes.clone();
 249:   }
 250: 
 251:   public byte[] getSignature()
 252:   {
 253:     return (byte[]) signature.clone();
 254:   }
 255: 
 256:   public String getSigAlgName()
 257:   {
 258:     if (sigAlgId.equals(ID_DSA_WITH_SHA1))
 259:       {
 260:         return "SHA1withDSA";
 261:       }
 262:     if (sigAlgId.equals(ID_RSA_WITH_MD2))
 263:       {
 264:         return "MD2withRSA";
 265:       }
 266:     if (sigAlgId.equals(ID_RSA_WITH_MD5))
 267:       {
 268:         return "MD5withRSA";
 269:       }
 270:     if (sigAlgId.equals(ID_RSA_WITH_SHA1))
 271:       {
 272:         return "SHA1withRSA";
 273:       }
 274:     return "unknown";
 275:   }
 276: 
 277:   public String getSigAlgOID()
 278:   {
 279:     return sigAlgId.toString();
 280:   }
 281: 
 282:   public byte[] getSigAlgParams()
 283:   {
 284:     return (byte[]) sigAlgVal.clone();
 285:   }
 286: 
 287:   public boolean[] getIssuerUniqueID()
 288:   {
 289:     if (issuerUniqueId != null)
 290:       {
 291:         return issuerUniqueId.toBooleanArray();
 292:       }
 293:     return null;
 294:   }
 295: 
 296:   public boolean[] getSubjectUniqueID()
 297:   {
 298:     if (subjectUniqueId != null)
 299:       {
 300:         return subjectUniqueId.toBooleanArray();
 301:       }
 302:     return null;
 303:   }
 304: 
 305:   public boolean[] getKeyUsage()
 306:   {
 307:     Extension e = getExtension(KeyUsage.ID);
 308:     if (e != null)
 309:       {
 310:         KeyUsage ku = (KeyUsage) e.getValue();
 311:         boolean[] result = new boolean[9];
 312:         boolean[] b = ku.getKeyUsage().toBooleanArray();
 313:         System.arraycopy(b, 0, result, 0, b.length);
 314:         return result;
 315:       }
 316:     return null;
 317:   }
 318: 
 319:   public List getExtendedKeyUsage() throws CertificateParsingException
 320:   {
 321:     Extension e = getExtension(ExtendedKeyUsage.ID);
 322:     if (e != null)
 323:       {
 324:         List a = ((ExtendedKeyUsage) e.getValue()).getPurposeIds();
 325:         List b = new ArrayList(a.size());
 326:         for (Iterator it = a.iterator(); it.hasNext(); )
 327:           {
 328:             b.add(it.next().toString());
 329:           }
 330:         return Collections.unmodifiableList(b);
 331:       }
 332:     return null;
 333:   }
 334: 
 335:   public int getBasicConstraints()
 336:   {
 337:     Extension e = getExtension(BasicConstraints.ID);
 338:     if (e != null)
 339:       {
 340:         return ((BasicConstraints) e.getValue()).getPathLengthConstraint();
 341:       }
 342:     return -1;
 343:   }
 344: 
 345:   public Collection getSubjectAlternativeNames()
 346:     throws CertificateParsingException
 347:   {
 348:     Extension e = getExtension(SubjectAlternativeNames.ID);
 349:     if (e != null)
 350:       {
 351:         return ((SubjectAlternativeNames) e.getValue()).getNames();
 352:       }
 353:     return null;
 354:   }
 355: 
 356:   public Collection getIssuerAlternativeNames()
 357:     throws CertificateParsingException
 358:   {
 359:     Extension e = getExtension(IssuerAlternativeNames.ID);
 360:     if (e != null)
 361:       {
 362:         return ((IssuerAlternativeNames) e.getValue()).getNames();
 363:       }
 364:     return null;
 365:   }
 366: 
 367: // X509Extension methods.
 368:   // ------------------------------------------------------------------------
 369: 
 370:   public boolean hasUnsupportedCriticalExtension()
 371:   {
 372:     for (Iterator it = extensions.values().iterator(); it.hasNext(); )
 373:       {
 374:         Extension e = (Extension) it.next();
 375:         if (e.isCritical() && !e.isSupported())
 376:           return true;
 377:       }
 378:     return false;
 379:   }
 380: 
 381:   public Set getCriticalExtensionOIDs()
 382:   {
 383:     HashSet s = new HashSet();
 384:     for (Iterator it = extensions.values().iterator(); it.hasNext(); )
 385:       {
 386:         Extension e = (Extension) it.next();
 387:         if (e.isCritical())
 388:           s.add(e.getOid().toString());
 389:       }
 390:     return Collections.unmodifiableSet(s);
 391:   }
 392: 
 393:   public Set getNonCriticalExtensionOIDs()
 394:   {
 395:     HashSet s = new HashSet();
 396:     for (Iterator it = extensions.values().iterator(); it.hasNext(); )
 397:       {
 398:         Extension e = (Extension) it.next();
 399:         if (!e.isCritical())
 400:           s.add(e.getOid().toString());
 401:       }
 402:     return Collections.unmodifiableSet(s);
 403:   }
 404: 
 405:   public byte[] getExtensionValue(String oid)
 406:   {
 407:     Extension e = getExtension(new OID(oid));
 408:     if (e != null)
 409:       {
 410:         return e.getValue().getEncoded();
 411:       }
 412:     return null;
 413:   }
 414: 
 415:   // GnuPKIExtension method.
 416:   // -------------------------------------------------------------------------
 417: 
 418:   public Extension getExtension(OID oid)
 419:   {
 420:     return (Extension) extensions.get(oid);
 421:   }
 422: 
 423:   public Collection getExtensions()
 424:   {
 425:     return extensions.values();
 426:   }
 427: 
 428:   // Certificate methods.
 429:   // -------------------------------------------------------------------------
 430: 
 431:   public byte[] getEncoded() throws CertificateEncodingException
 432:   {
 433:     return (byte[]) encoded.clone();
 434:   }
 435: 
 436:   public void verify(PublicKey key)
 437:     throws CertificateException, NoSuchAlgorithmException,
 438:            InvalidKeyException, NoSuchProviderException, SignatureException
 439:   {
 440:     Signature sig = Signature.getInstance(sigAlgId.toString());
 441:     doVerify(sig, key);
 442:   }
 443: 
 444:   public void verify(PublicKey key, String provider)
 445:     throws CertificateException, NoSuchAlgorithmException,
 446:            InvalidKeyException, NoSuchProviderException, SignatureException
 447:   {
 448:     Signature sig = Signature.getInstance(sigAlgId.toString(), provider);
 449:     doVerify(sig, key);
 450:   }
 451: 
 452:   public String toString()
 453:   {
 454:     StringWriter str = new StringWriter();
 455:     PrintWriter out = new PrintWriter(str);
 456:     out.println(X509Certificate.class.getName() + " {");
 457:     out.println("  TBSCertificate {");
 458:     out.println("    version = " + version + ";");
 459:     out.println("    serialNo = " + serialNo + ";");
 460:     out.println("    signature = {");
 461:     out.println("      algorithm = " + getSigAlgName() + ";");
 462:     out.print("      parameters =");
 463:     if (sigAlgVal != null)
 464:       {
 465:         out.println();
 466:         out.print(Util.hexDump(sigAlgVal, "        "));
 467:       }
 468:     else
 469:       {
 470:         out.println(" null;");
 471:       }
 472:     out.println("    }");
 473:     out.println("    issuer = " + issuer.getName() + ";");
 474:     out.println("    validity = {");
 475:     out.println("      notBefore = " + notBefore + ";");
 476:     out.println("      notAfter  = " + notAfter + ";");
 477:     out.println("    }");
 478:     out.println("    subject = " + subject.getName() + ";");
 479:     out.println("    subjectPublicKeyInfo = {");
 480:     out.println("      algorithm = " + subjectKey.getAlgorithm());
 481:     out.println("      key =");
 482:     out.print(Util.hexDump(subjectKey.getEncoded(), "        "));
 483:     out.println("    };");
 484:     out.println("    issuerUniqueId  = " + issuerUniqueId + ";");
 485:     out.println("    subjectUniqueId = " + subjectUniqueId + ";");
 486:     out.println("    extensions = {");
 487:     for (Iterator it = extensions.values().iterator(); it.hasNext(); )
 488:       {
 489:         out.println("      " + it.next());
 490:       }
 491:     out.println("    }");
 492:     out.println("  }");
 493:     out.println("  signatureAlgorithm = " + getSigAlgName() + ";");
 494:     out.println("  signatureValue =");
 495:     out.print(Util.hexDump(signature, "    "));
 496:     out.println("}");
 497:     return str.toString();
 498:   }
 499: 
 500:   public PublicKey getPublicKey()
 501:   {
 502:     return subjectKey;
 503:   }
 504: 
 505:   public boolean equals(Object other)
 506:   {
 507:     if (!(other instanceof X509Certificate))
 508:       return false;
 509:     try
 510:       {
 511:         if (other instanceof X509Certificate)
 512:           return Arrays.equals(encoded, ((X509Certificate) other).encoded);
 513:         byte[] enc = ((X509Certificate) other).getEncoded();
 514:         if (enc == null)
 515:           return false;
 516:         return Arrays.equals(encoded, enc);
 517:       }
 518:     catch (CertificateEncodingException cee)
 519:       {
 520:         return false;
 521:       }
 522:   }
 523: 
 524:   // Own methods.
 525:   // ------------------------------------------------------------------------
 526: 
 527:   /**
 528:    * Verify this certificate's signature.
 529:    */
 530:   private void doVerify(Signature sig, PublicKey key)
 531:     throws CertificateException, InvalidKeyException, SignatureException
 532:   {
 533:     logger.log (Component.X509, "verifying sig={0} key={1}",
 534:                 new Object[] { sig, key });
 535:     sig.initVerify(key);
 536:     sig.update(tbsCertBytes);
 537:     if (!sig.verify(signature))
 538:       {
 539:         throw new CertificateException("signature not validated");
 540:       }
 541:   }
 542: 
 543:   /**
 544:    * Parse a DER stream into an X.509 certificate.
 545:    *
 546:    * @param encoded The encoded bytes.
 547:    */
 548:   private void parse(InputStream encoded) throws Exception
 549:   {
 550:     DERReader der = new DERReader(encoded);
 551: 
 552:     // Certificate ::= SEQUENCE {
 553:     DERValue cert = der.read();
 554:     logger.log (Component.X509, "start Certificate  len == {0}",
 555:                 Integer.valueOf(cert.getLength()));
 556: 
 557:     this.encoded = cert.getEncoded();
 558:     if (!cert.isConstructed())
 559:       {
 560:         throw new IOException("malformed Certificate");
 561:       }
 562: 
 563:     // TBSCertificate ::= SEQUENCE {
 564:     DERValue tbsCert = der.read();
 565:     if (tbsCert.getValue() != DER.CONSTRUCTED_VALUE)
 566:       {
 567:         throw new IOException("malformed TBSCertificate");
 568:       }
 569:     tbsCertBytes = tbsCert.getEncoded();
 570:     logger.log (Component.X509, "start TBSCertificate  len == {0}",
 571:                 Integer.valueOf(tbsCert.getLength()));
 572: 
 573:     // Version ::= INTEGER [0] { v1(0), v2(1), v3(2) }
 574:     DERValue val = der.read();
 575:     if (val.getTagClass() == DER.CONTEXT && val.getTag() == 0)
 576:       {
 577:         version = ((BigInteger) der.read().getValue()).intValue() + 1;
 578:         val = der.read();
 579:       }
 580:     else
 581:       {
 582:         version = 1;
 583:       }
 584:     logger.log (Component.X509, "read version == {0}",
 585:                 Integer.valueOf(version));
 586: 
 587:     // SerialNumber ::= INTEGER
 588:     serialNo = (BigInteger) val.getValue();
 589:     logger.log (Component.X509, "read serial number == {0}", serialNo);
 590: 
 591:     // AlgorithmIdentifier ::= SEQUENCE {
 592:     val = der.read();
 593:     if (!val.isConstructed())
 594:       {
 595:         throw new IOException("malformed AlgorithmIdentifier");
 596:       }
 597:     int certAlgLen = val.getLength();
 598:     logger.log (Component.X509, "start AlgorithmIdentifier  len == {0}",
 599:                 Integer.valueOf(certAlgLen));
 600:     val = der.read();
 601: 
 602:     //   algorithm    OBJECT IDENTIFIER,
 603:     algId = (OID) val.getValue();
 604:     logger.log (Component.X509, "read algorithm ID == {0}", algId);
 605: 
 606:     //   parameters   ANY DEFINED BY algorithm OPTIONAL }
 607:     if (certAlgLen > val.getEncodedLength())
 608:       {
 609:         val = der.read();
 610:         if (val == null)
 611:           {
 612:             algVal = null;
 613:           }
 614:         else
 615:           {
 616:             algVal = val.getEncoded();
 617: 
 618:             if (val.isConstructed())
 619:               encoded.skip(val.getLength());
 620:           }
 621:         logger.log (Component.X509, "read algorithm parameters == {0}", algVal);
 622:       }
 623: 
 624:     // issuer   Name,
 625:     val = der.read();
 626:     issuer = new X500DistinguishedName(val.getEncoded());
 627:     der.skip(val.getLength());
 628:     logger.log (Component.X509, "read issuer == {0}", issuer);
 629: 
 630:     // Validity ::= SEQUENCE {
 631:     //   notBefore   Time,
 632:     //   notAfter    Time }
 633:     if (!der.read().isConstructed())
 634:       {
 635:         throw new IOException("malformed Validity");
 636:       }
 637:     notBefore = (Date) der.read().getValue();
 638:     logger.log (Component.X509, "read notBefore == {0}", notBefore);
 639:     notAfter  = (Date) der.read().getValue();
 640:     logger.log (Component.X509, "read notAfter == {0}", notAfter);
 641: 
 642:     // subject   Name,
 643:     val = der.read();
 644:     subject = new X500DistinguishedName(val.getEncoded());
 645:     der.skip(val.getLength());
 646:     logger.log (Component.X509, "read subject == {0}", subject);
 647: 
 648:     // SubjectPublicKeyInfo ::= SEQUENCE {
 649:     //   algorithm         AlgorithmIdentifier,
 650:     //   subjectPublicKey  BIT STRING }
 651:     DERValue spki = der.read();
 652:     if (!spki.isConstructed())
 653:       {
 654:         throw new IOException("malformed SubjectPublicKeyInfo");
 655:       }
 656:     KeyFactory spkFac = KeyFactory.getInstance("X.509");
 657:     subjectKey = spkFac.generatePublic(new X509EncodedKeySpec(spki.getEncoded()));
 658:     der.skip(spki.getLength());
 659:     logger.log (Component.X509, "read subjectPublicKey == {0}", subjectKey);
 660: 
 661:     val = der.read();
 662:     if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 1)
 663:       {
 664:         byte[] b = (byte[]) val.getValue();
 665:         issuerUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
 666:         logger.log (Component.X509, "read issuerUniqueId == {0}", issuerUniqueId);
 667:         val = der.read();
 668:       }
 669:     if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 2)
 670:       {
 671:         byte[] b = (byte[]) val.getValue();
 672:         subjectUniqueId = new BitString(b, 1, b.length-1, b[0] & 0xFF);
 673:         logger.log (Component.X509, "read subjectUniqueId == {0}", subjectUniqueId);
 674:         val = der.read();
 675:       }
 676:     if (version >= 3 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 3)
 677:       {
 678:         val = der.read();
 679:         logger.log (Component.X509, "start Extensions  len == {0}",
 680:                     Integer.valueOf(val.getLength()));
 681:         int len = 0;
 682:         while (len < val.getLength())
 683:           {
 684:             DERValue ext = der.read();
 685:             logger.log (Component.X509, "start extension  len == {0}",
 686:                         Integer.valueOf(ext.getLength()));
 687:             Extension e = new Extension(ext.getEncoded());
 688:             extensions.put(e.getOid(), e);
 689:             der.skip(ext.getLength());
 690:             len += ext.getEncodedLength();
 691:             logger.log (Component.X509, "read extension {0} == {1}",
 692:                         new Object[] { e.getOid (), e });
 693:             logger.log (Component.X509, "count == {0}", Integer.valueOf(len));
 694:           }
 695: 
 696:         val = der.read ();
 697:       }
 698: 
 699:     logger.log (Component.X509, "read value {0}", val);
 700:     if (!val.isConstructed())
 701:       {
 702:         throw new CertificateException ("malformed AlgorithmIdentifier");
 703:       }
 704:     int sigAlgLen = val.getLength();
 705:     logger.log (Component.X509, "start AlgorithmIdentifier  len == {0}",
 706:                 Integer.valueOf(sigAlgLen));
 707:     val = der.read();
 708:     sigAlgId = (OID) val.getValue();
 709:     logger.log (Component.X509, "read algorithm id == {0}", sigAlgId);
 710:     if (sigAlgLen > val.getEncodedLength())
 711:       {
 712:         val = der.read();
 713:         if (val.getValue() == null)
 714:           {
 715:             if (subjectKey instanceof DSAPublicKey)
 716:               {
 717:                 AlgorithmParameters params =
 718:                   AlgorithmParameters.getInstance("DSA");
 719:                 DSAParams dsap = ((DSAPublicKey) subjectKey).getParams();
 720:                 DSAParameterSpec spec =
 721:                   new DSAParameterSpec(dsap.getP(), dsap.getQ(), dsap.getG());
 722:                 params.init(spec);
 723:                 sigAlgVal = params.getEncoded();
 724:               }
 725:           }
 726:         else
 727:           {
 728:             sigAlgVal = (byte[]) val.getEncoded();
 729:           }
 730:         if (val.isConstructed())
 731:           {
 732:             encoded.skip(val.getLength());
 733:           }
 734:         logger.log (Component.X509, "read parameters == {0}", sigAlgVal);
 735:       }
 736:     signature = ((BitString) der.read().getValue()).toByteArray();
 737:     logger.log (Component.X509, "read signature ==\n{0}", Util.hexDump(signature, ">>>> "));
 738:   }
 739: }