debug("read signature ==\n" + Util.hexDump(signature, ">>>> "));
  private void parse(InputStream encoded) throws Exception  {    DERReader der = new DERReader(encoded);    // Certificate ::= SEQUENCE {    DERValue cert = der.read();    this.encoded = cert.getEncoded();    if (!cert.isConstructed())      throw new ASN1ParsingException("malformed Certificate");    // TBSCertificate ::= SEQUENCE {    DERValue tbsCert = der.read();    if (tbsCert.getValue() != DER.CONSTRUCTED_VALUE)      throw new ASN1ParsingException("malformed TBSCertificate");    tbsCertBytes = tbsCert.getEncoded();    DERValue val = der.read();    if (val.getTagClass() == DER.CONTEXT && val.getTag() == 0)      {        // Version ::= INTEGER [0] { v1(0), v2(1), v3(2) }        version = ((BigInteger) der.read().getValue()).intValue() + 1;        val = der.read();      }    else      {        version = 1;      }    // SerialNumber ::= INTEGER    serialNo = (BigInteger) val.getValue();    // AlgorithmIdentifier ::= SEQUENCE {    val = der.read();    if (!val.isConstructed())      throw new ASN1ParsingException("malformed AlgorithmIdentifier");    int certAlgLen = val.getLength();    val = der.read();    algId = (OID) val.getValue();    if (certAlgLen > val.getEncodedLength())      {        val = der.read();        if (val == null)          algVal = null;        else          algVal = val.getEncoded();        if (val.isConstructed())          encoded.skip(val.getLength());      }    issuer = new X500Principal(encoded);    if (!der.read().isConstructed())      throw new ASN1ParsingException("malformed Validity");    notBefore = (Date) der.read().getValue();    notAfter  = (Date) der.read().getValue();    subject = new X500Principal(encoded);    if (!der.read().isConstructed())      throw new ASN1ParsingException("malformed SubjectPublicKeyInfo");       val = der.read();    if (!val.isConstructed())      throw new ASN1ParsingException("malformed AlgorithmIdentifier");    int keyAlgLen = val.getLength();    val = der.read();    OID keyID = (OID) val.getValue();    byte[] keyParams = null;    if (keyAlgLen > val.getEncodedLength())      {        val = der.read();        keyParams = val.getEncoded();        if (algVal == null)          algVal = keyParams;        if (val.isConstructed())          encoded.skip(val.getLength());      }    val = der.read();    byte[] keyVal = ((BitString) val.getValue()).toByteArray();    if (keyID.equals(ID_DSA))      {        AlgorithmParameters params = AlgorithmParameters.getInstance("DSA");        params.init(keyParams, "ASN.1");        KeyFactory keyFac = KeyFactory.getInstance("DSA");        DSAParameterSpec spec = (DSAParameterSpec)          params.getParameterSpec(DSAParameterSpec.class);        subjectKey = keyFac.generatePublic(new DSAPublicKeySpec(          (BigInteger) new DERReader(keyVal).read().getValue(),          spec.getP(), spec.getQ(), spec.getG()));      }    else if (keyID.equals(ID_RSA))      {        KeyFactory keyFac = KeyFactory.getInstance("RSA");        DERReader rsaKey = new DERReader(keyVal);        if (!rsaKey.read().isConstructed())          throw new ASN1ParsingException("malformed RSAPublicKey");        subjectKey = keyFac.generatePublic(new RSAPublicKeySpec(          (BigInteger) rsaKey.read().getValue(),          (BigInteger) rsaKey.read().getValue()));      }    else      throw new ASN1ParsingException("unknown key algorithm " + keyID);    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);        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);        val = der.read();      }    if (version >= 3 && val.getTagClass() != DER.UNIVERSAL && val.getTag() == 3)      {        val = der.read();        int len = 0;        while (len < val.getLength())          {            DERValue ext = der.read();            OID extId = (OID) der.read().getValue();            DERValue val2 = der.read();            Boolean crit = Boolean.valueOf(false);            if (val2.getValue() instanceof Boolean)              {                crit = (Boolean) val2.getValue();                val2 = der.read();              }            byte[] extVal = (byte[]) val2.getValue();            extensions.put(extId.toString(), extVal);            if (crit.booleanValue())              critOids.add(extId.toString());            else              nonCritOids.add(extId.toString());            if (extId.equals(ID_KEY_USAGE))              {                keyUsage = (BitString) DERReader.read(extVal).getValue();              }            else if (extId.equals(ID_BASIC_CONSTRAINTS))              {                DERReader bc = new DERReader(extVal);                DERValue constraints = bc.read();                if (!constraints.isConstructed())                  throw new ASN1ParsingException("malformed BasicConstraints");                if (constraints.getLength() > 0)                  {                    boolean ca = false;                    int constr = -1;                    val2 = bc.read();                    if (val2.getValue() instanceof Boolean)                      {                        ca = ((Boolean) val2.getValue()).booleanValue();                        if (constraints.getLength() > val2.getEncodedLength())                          val2 = bc.read();                      }                    if (val2.getValue() instanceof BigInteger)                      constr = ((BigInteger) val2.getValue()).intValue();                    basicConstraints = constr;                  }              }            len += ext.getEncodedLength();          }      }    val = der.read();    if (!val.isConstructed())      throw new ASN1ParsingException("malformed AlgorithmIdentifier");    int sigAlgLen = val.getLength();    val = der.read();    sigAlgId = (OID) val.getValue();    if (sigAlgLen > val.getEncodedLength())      {        val = der.read();        if (val.getValue() == null)          sigAlgVal = keyParams;        else          sigAlgVal = (byte[]) val.getEncoded();        if (val.isConstructed())          encoded.skip(val.getLength());      }    signature = ((BitString) der.read().getValue()).toByteArray();  }