public boolean hasUnsupportedCriticalExtension() {
   for (Iterator it = extensions.values().iterator(); it.hasNext(); ) {
     Extension e = (Extension) it.next();
     if (e.isCritical() && !e.isSupported()) return true;
   }
   return false;
 }
 public byte[] getExtensionValue(String oid) {
   Extension e = getExtension(new OID(oid));
   if (e != null) {
     return e.getValue().getEncoded();
   }
   return null;
 }
 public Collection getIssuerAlternativeNames() throws CertificateParsingException {
   Extension e = getExtension(IssuerAlternativeNames.ID);
   if (e != null) {
     return ((IssuerAlternativeNames) e.getValue()).getNames();
   }
   return null;
 }
 public int getBasicConstraints() {
   Extension e = getExtension(BasicConstraints.ID);
   if (e != null) {
     return ((BasicConstraints) e.getValue()).getPathLengthConstraint();
   }
   return -1;
 }
 public Set getNonCriticalExtensionOIDs() {
   HashSet s = new HashSet();
   for (Iterator it = extensions.values().iterator(); it.hasNext(); ) {
     Extension e = (Extension) it.next();
     if (!e.isCritical()) s.add(e.getOid().toString());
   }
   return Collections.unmodifiableSet(s);
 }
 public boolean[] getKeyUsage() {
   Extension e = getExtension(KeyUsage.ID);
   if (e != null) {
     KeyUsage ku = (KeyUsage) e.getValue();
     boolean[] result = new boolean[9];
     boolean[] b = ku.getKeyUsage().toBooleanArray();
     System.arraycopy(b, 0, result, 0, b.length);
     return result;
   }
   return null;
 }
 public List getExtendedKeyUsage() throws CertificateParsingException {
   Extension e = getExtension(ExtendedKeyUsage.ID);
   if (e != null) {
     List a = ((ExtendedKeyUsage) e.getValue()).getPurposeIds();
     List b = new ArrayList(a.size());
     for (Iterator it = a.iterator(); it.hasNext(); ) {
       b.add(it.next().toString());
     }
     return Collections.unmodifiableList(b);
   }
   return null;
 }
  /**
   * Parse a DER stream into an X.509 certificate.
   *
   * @param encoded The encoded bytes.
   */
  private void parse(InputStream encoded) throws Exception {
    DERReader der = new DERReader(encoded);

    // Certificate ::= SEQUENCE {
    DERValue cert = der.read();
    debug("start Certificate  len == " + cert.getLength());

    this.encoded = cert.getEncoded();
    if (!cert.isConstructed()) {
      throw new IOException("malformed Certificate");
    }

    // TBSCertificate ::= SEQUENCE {
    DERValue tbsCert = der.read();
    if (tbsCert.getValue() != DER.CONSTRUCTED_VALUE) {
      throw new IOException("malformed TBSCertificate");
    }
    tbsCertBytes = tbsCert.getEncoded();
    debug("start TBSCertificate  len == " + tbsCert.getLength());

    // Version ::= INTEGER [0] { v1(0), v2(1), v3(2) }
    DERValue val = der.read();
    if (val.getTagClass() == DER.CONTEXT && val.getTag() == 0) {
      version = ((BigInteger) der.read().getValue()).intValue() + 1;
      val = der.read();
    } else {
      version = 1;
    }
    debug("read version == " + version);

    // SerialNumber ::= INTEGER
    serialNo = (BigInteger) val.getValue();
    debug("read serial number == " + serialNo);

    // AlgorithmIdentifier ::= SEQUENCE {
    val = der.read();
    if (!val.isConstructed()) {
      throw new IOException("malformed AlgorithmIdentifier");
    }
    int certAlgLen = val.getLength();
    debug("start AlgorithmIdentifier  len == " + certAlgLen);
    val = der.read();

    //   algorithm    OBJECT IDENTIFIER,
    algId = (OID) val.getValue();
    debug("read algorithm ID == " + algId);

    //   parameters   ANY DEFINED BY algorithm OPTIONAL }
    if (certAlgLen > val.getEncodedLength()) {
      val = der.read();
      if (val == null) {
        algVal = null;
      } else {
        algVal = val.getEncoded();
      }
      if (val.isConstructed()) {
        encoded.skip(val.getLength());
      }
      debug("read algorithm parameters == " + algVal);
    }

    // issuer   Name,
    val = der.read();
    issuer = new X500Name(val.getEncoded());
    der.skip(val.getLength());
    debug("read issuer == " + issuer);

    // Validity ::= SEQUENCE {
    //   notBefore   Time,
    //   notAfter    Time }
    if (!der.read().isConstructed()) {
      throw new IOException("malformed Validity");
    }
    notBefore = (Date) der.read().getValue();
    notAfter = (Date) der.read().getValue();
    debug("read notBefore == " + notBefore);
    debug("read notAfter == " + notAfter);

    // subject   Name,
    val = der.read();
    subject = new X500Name(val.getEncoded());
    der.skip(val.getLength());
    debug("read subject == " + subject);

    // SubjectPublicKeyInfo ::= SEQUENCE {
    //   algorithm         AlgorithmIdentifier,
    //   subjectPublicKey  BIT STRING }
    DERValue spki = der.read();
    if (!spki.isConstructed()) {
      throw new IOException("malformed SubjectPublicKeyInfo");
    }
    KeyFactory spkFac = KeyFactory.getInstance("X.509");
    subjectKey = spkFac.generatePublic(new X509EncodedKeySpec(spki.getEncoded()));
    der.skip(spki.getLength());
    debug("read subjectPublicKey == " + subjectKey);

    if (version > 1) {
      val = der.read();
    }
    if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 1) {
      byte[] b = (byte[]) val.getValue();
      issuerUniqueId = new BitString(b, 1, b.length - 1, b[0] & 0xFF);
      debug("read issuerUniqueId == " + issuerUniqueId);
      val = der.read();
    }
    if (version >= 2 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 2) {
      byte[] b = (byte[]) val.getValue();
      subjectUniqueId = new BitString(b, 1, b.length - 1, b[0] & 0xFF);
      debug("read subjectUniqueId == " + subjectUniqueId);
      val = der.read();
    }
    if (version >= 3 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 3) {
      val = der.read();
      debug("start Extensions  len == " + val.getLength());
      int len = 0;
      while (len < val.getLength()) {
        DERValue ext = der.read();
        debug("start extension  len == " + ext.getLength());
        Extension e = new Extension(ext.getEncoded());
        extensions.put(e.getOid(), e);
        der.skip(ext.getLength());
        len += ext.getEncodedLength();
        debug("count == " + len);
      }
    }

    val = der.read();
    if (!val.isConstructed()) {
      throw new IOException("malformed AlgorithmIdentifier");
    }
    int sigAlgLen = val.getLength();
    debug("start AlgorithmIdentifier  len == " + sigAlgLen);
    val = der.read();
    sigAlgId = (OID) val.getValue();
    debug("read algorithm id == " + sigAlgId);
    if (sigAlgLen > val.getEncodedLength()) {
      val = der.read();
      if (val.getValue() == null) {
        if (subjectKey instanceof DSAPublicKey) {
          AlgorithmParameters params = AlgorithmParameters.getInstance("DSA");
          DSAParams dsap = ((DSAPublicKey) subjectKey).getParams();
          DSAParameterSpec spec = new DSAParameterSpec(dsap.getP(), dsap.getQ(), dsap.getG());
          params.init(spec);
          sigAlgVal = params.getEncoded();
        }
      } else {
        sigAlgVal = (byte[]) val.getEncoded();
      }
      if (val.isConstructed()) {
        encoded.skip(val.getLength());
      }
      debug("read parameters == " + sigAlgVal);
    }
    signature = ((BitString) der.read().getValue()).toByteArray();
    debug("read signature ==\n" + Util.hexDump(signature, ">>>> "));
  }