Beispiel #1
0
        /*
         * 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);
        }
Beispiel #2
0
    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();
        }
    }
Beispiel #3
0
        /*
         * 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");
        }