/* * Generic parsing. If 'strictStrings' is true, then the following * rules are enforced: * -- Every SET in the sequence of RDN must have size 1. * -- Every name element is decoded as a string (by tag). * * If 'strictStrings' is false, then multiple elements may appear * in each SET, and values needs not be decodable as string (values * with a known OID must still be decodable). * * This constructor checks that within a single RDN, no two * attributes may have the same type. * * On decoding error, an AsnException is thrown. */ public X500Name(AsnElt aDN, bool strictStrings) { /* * Note: the SEQUENCE tag MUST be present, since the * ASN.1 definition of Name starts with a CHOICE; thus, * any tag override would have to be explicit, not * implicit. */ aDN.CheckConstructed(); aDN.CheckTag(AsnElt.SEQUENCE); List <List <DNPart> > r = new List <List <DNPart> >(); foreach (AsnElt aRDN in aDN.Sub) { aRDN.CheckConstructed(); aRDN.CheckTag(AsnElt.SET); aRDN.CheckNumSubMin(1); int n = aRDN.Sub.Length; if (n != 1 && strictStrings) { throw new AsnException(String.Format( "several ({0}) values in RDN", n)); } List <DNPart> r2 = new List <DNPart>(); r.Add(r2); for (int i = 0; i < n; i++) { AsnElt aTV = aRDN.Sub[i]; aTV.CheckConstructed(); aTV.CheckTag(AsnElt.SEQUENCE); aTV.CheckNumSub(2); AsnElt aOID = aTV.GetSub(0); aOID.CheckTag(AsnElt.OBJECT_IDENTIFIER); AsnElt aVal = aTV.GetSub(1); string nt = aOID.GetOID(); DNPart dnp = new DNPart(nt, aVal); if (strictStrings && !dnp.IsString) { throw new AsnException( "RDN is not a string"); } r2.Add(dnp); } } Init(r); }
void ProcessAltNames(byte[] extVal, bool forIssuer) { /* * Alternative names processing. * * If the extension contains an X.500 name, and the * corresponding DN in the certificate TBS is empty, * then that X.500 name will be used as subjectDN or * issuerDN. However, if the extension contains several * X.500 names, or if the DN in the TBS is non-empty, * then the X.500 name(s) in the extension will be * ignored. * * For the subject, we also gather dNSNames into * the "serverNames" array. */ List <string> dnsNames = new List <string>(); AsnElt ae = AsnElt.Decode(extVal); ae.CheckTag(AsnElt.SEQUENCE); ae.CheckConstructed(); bool foundDN = false; X500Name dn = null; foreach (AsnElt agn in ae.Sub) { if (agn.TagClass != AsnElt.CONTEXT) { continue; } switch (agn.TagValue) { case 2: dnsNames.Add(agn.GetString(AsnElt.IA5String)); break; case 4: /* * Since "Name" is a CHOICE, the context * tag applied on it as part of the * GeneralName structure is EXPLICIT. We * have to remove it. */ agn.CheckNumSub(1); AsnElt adn = agn.GetSub(0); if (!foundDN) { dn = new X500Name(adn, false); } else { dn = null; } foundDN = true; break; } } if (foundDN && dn != null) { if (forIssuer) { if (issuerDN.IsEmpty) { issuerDN = dn; } } else { if (subjectDN.IsEmpty) { subjectDN = dn; } } } if (!forIssuer && dnsNames.Count > 0) { serverNames = dnsNames.ToArray(); } }
/* * Decode the provided private key. This method accepts both * PKCS#8 and the "internal" format; the source object may be * raw DER, Base64-encoded DER, or PEM. The key type is * automatically detected. */ public static IPrivateKey DecodePrivateKey(byte[] enc) { string pemType; enc = AsnIO.FindBER(enc, false, out pemType); if (enc == null) { throw new AsnException("Not an encoded object"); } AsnElt ak = AsnElt.Decode(enc); ak.CheckConstructed(); if (pemType != null) { switch (pemType) { case "RSA PRIVATE KEY": return(DecodePrivateKeyRSA(ak)); /* disabled DSA * case "DSA PRIVATE KEY": * return DecodePrivateKeyDSA(ak); */ case "EC PRIVATE KEY": return(DecodePrivateKeyEC(ak)); case "PRIVATE KEY": return(DecodePrivateKeyPKCS8(ak)); default: throw new AsnException( "Unknown PEM object: " + pemType); } } if (ak.Sub.Length == 3 && ak.GetSub(0).TagValue == AsnElt.INTEGER && ak.GetSub(1).TagValue == AsnElt.SEQUENCE && ak.GetSub(2).TagValue == AsnElt.OCTET_STRING) { return(DecodePrivateKeyPKCS8(ak)); } if (ak.Sub.Length >= 9) { bool mayBeRSA = true; for (int i = 0; i < 9; i++) { if (ak.GetSub(i).TagValue != AsnElt.INTEGER) { mayBeRSA = false; break; } } if (mayBeRSA) { return(DecodePrivateKeyRSA(ak)); } } /* disabled DSA * if (ak.Sub.Length >= 6) { * bool mayBeDSA = true; * for (int i = 0; i < 6; i ++) { * if (ak.GetSub(i).TagValue != AsnElt.INTEGER) { * mayBeDSA = false; * break; * } * } * if (mayBeDSA) { * return DecodePrivateKeyDSA(ak); * } * } */ if (ak.Sub.Length >= 2 && ak.GetSub(0).TagValue == AsnElt.INTEGER && ak.GetSub(1).TagValue == AsnElt.OCTET_STRING) { return(DecodePrivateKeyEC(ak)); } throw new AsnException("Unrecognized private key format"); }