private void Parse(byte[] crl) { string e = "Input data cannot be coded as a valid CRL."; try { // CertificateList ::= SEQUENCE { ASN1 encodedCRL = new ASN1(encoded); if ((encodedCRL.Tag != 0x30) || (encodedCRL.Count != 3)) { throw new CryptographicException(e); } // CertificateList / TBSCertList, ASN1 toBeSigned = encodedCRL [0]; if ((toBeSigned.Tag != 0x30) || (toBeSigned.Count < 3)) { throw new CryptographicException(e); } int n = 0; // CertificateList / TBSCertList / Version OPTIONAL, -- if present, MUST be v2 if (toBeSigned [n].Tag == 0x02) { version = (byte)(toBeSigned [n++].Value [0] + 1); } else { version = 1; // DEFAULT } // CertificateList / TBSCertList / AlgorithmIdentifier, signatureOID = ASN1Convert.ToOid(toBeSigned [n++][0]); // CertificateList / TBSCertList / Name, issuer = X501.ToString(toBeSigned [n++]); // CertificateList / TBSCertList / Time, thisUpdate = ASN1Convert.ToDateTime(toBeSigned [n++]); // CertificateList / TBSCertList / Time OPTIONAL, ASN1 next = toBeSigned [n++]; if ((next.Tag == 0x17) || (next.Tag == 0x18)) { nextUpdate = ASN1Convert.ToDateTime(next); next = toBeSigned [n++]; } // CertificateList / TBSCertList / revokedCertificates SEQUENCE OF SEQUENCE { entries = new ArrayList(); // this is OPTIONAL so it may not be present if no entries exists if ((next != null) && (next.Tag == 0x30)) { ASN1 revokedCertificates = next; for (int i = 0; i < revokedCertificates.Count; i++) { entries.Add(new X509CrlEntry(revokedCertificates [i])); } } else { n--; } // CertificateList / TBSCertList / crlExtensions [0] Extensions OPTIONAL } ASN1 extns = toBeSigned [n]; if ((extns != null) && (extns.Tag == 0xA0) && (extns.Count == 1)) { extensions = new X509ExtensionCollection(extns [0]); } else { extensions = new X509ExtensionCollection(null); // result in a read only object } // CertificateList / AlgorithmIdentifier string signatureAlgorithm = ASN1Convert.ToOid(encodedCRL [1][0]); if (signatureOID != signatureAlgorithm) { throw new CryptographicException(e + " [Non-matching signature algorithms in CRL]"); } // CertificateList / BIT STRING byte[] bitstring = encodedCRL [2].Value; // first byte contains unused bits in first byte signature = new byte [bitstring.Length - 1]; Buffer.BlockCopy(bitstring, 1, signature, 0, signature.Length); } catch { throw new CryptographicException(e); } }
// that's were the real job is! private void Parse(byte[] data) { try { decoder = new ASN1(data); // Certificate if (decoder.Tag != 0x30) { throw new CryptographicException(encoding_error); } // Certificate / TBSCertificate if (decoder [0].Tag != 0x30) { throw new CryptographicException(encoding_error); } ASN1 tbsCertificate = decoder [0]; int tbs = 0; // Certificate / TBSCertificate / Version ASN1 v = decoder [0][tbs]; version = 1; // DEFAULT v1 if ((v.Tag == 0xA0) && (v.Count > 0)) { // version (optional) is present only in v2+ certs version += v [0].Value [0]; // zero based tbs++; } // Certificate / TBSCertificate / CertificateSerialNumber ASN1 sn = decoder [0][tbs++]; if (sn.Tag != 0x02) { throw new CryptographicException(encoding_error); } serialnumber = sn.Value; Array.Reverse(serialnumber, 0, serialnumber.Length); // Certificate / TBSCertificate / AlgorithmIdentifier tbs++; // ASN1 signatureAlgo = tbsCertificate.Element (tbs++, 0x30); issuer = tbsCertificate.Element(tbs++, 0x30); m_issuername = X501.ToString(issuer); ASN1 validity = tbsCertificate.Element(tbs++, 0x30); ASN1 notBefore = validity [0]; m_from = ASN1Convert.ToDateTime(notBefore); ASN1 notAfter = validity [1]; m_until = ASN1Convert.ToDateTime(notAfter); subject = tbsCertificate.Element(tbs++, 0x30); m_subject = X501.ToString(subject); ASN1 subjectPublicKeyInfo = tbsCertificate.Element(tbs++, 0x30); ASN1 algorithm = subjectPublicKeyInfo.Element(0, 0x30); ASN1 algo = algorithm.Element(0, 0x06); m_keyalgo = ASN1Convert.ToOid(algo); // parameters ANY DEFINED BY algorithm OPTIONAL // so we dont ask for a specific (Element) type and return DER ASN1 parameters = algorithm [1]; m_keyalgoparams = ((algorithm.Count > 1) ? parameters.GetBytes() : null); ASN1 subjectPublicKey = subjectPublicKeyInfo.Element(1, 0x03); // we must drop th first byte (which is the number of unused bits // in the BITSTRING) int n = subjectPublicKey.Length - 1; m_publickey = new byte [n]; Buffer.BlockCopy(subjectPublicKey.Value, 1, m_publickey, 0, n); // signature processing byte[] bitstring = decoder [2].Value; // first byte contains unused bits in first byte signature = new byte [bitstring.Length - 1]; Buffer.BlockCopy(bitstring, 1, signature, 0, signature.Length); algorithm = decoder [1]; algo = algorithm.Element(0, 0x06); m_signaturealgo = ASN1Convert.ToOid(algo); parameters = algorithm [1]; if (parameters != null) { m_signaturealgoparams = parameters.GetBytes(); } else { m_signaturealgoparams = null; } // Certificate / TBSCertificate / issuerUniqueID ASN1 issuerUID = tbsCertificate.Element(tbs, 0x81); if (issuerUID != null) { tbs++; issuerUniqueID = issuerUID.Value; } // Certificate / TBSCertificate / subjectUniqueID ASN1 subjectUID = tbsCertificate.Element(tbs, 0x82); if (subjectUID != null) { tbs++; subjectUniqueID = subjectUID.Value; } // Certificate / TBSCertificate / Extensions ASN1 extns = tbsCertificate.Element(tbs, 0xA3); if ((extns != null) && (extns.Count == 1)) { extensions = new X509ExtensionCollection(extns [0]); } else { extensions = new X509ExtensionCollection(null); } // keep a copy of the original data m_encodedcert = (byte[])data.Clone(); } catch (Exception ex) { throw new CryptographicException(encoding_error, ex); } }