Source for gnu.java.security.x509.X509Certificate

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