예제 #1
0
        public void Load(
            Stream input,
            char[]      password)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            if (password == null)
            {
                throw new ArgumentNullException("password");
            }

            Asn1Sequence obj             = (Asn1Sequence)Asn1Object.FromStream(input);
            Pfx          bag             = new Pfx(obj);
            ContentInfo  info            = bag.AuthSafe;
            bool         unmarkedKey     = false;
            bool         wrongPkcs12Zero = false;

            if (bag.MacData != null) // check the mac code
            {
                MacData             mData = bag.MacData;
                DigestInfo          dInfo = mData.Mac;
                AlgorithmIdentifier algId = dInfo.AlgorithmID;
                byte[] salt    = mData.GetSalt();
                int    itCount = mData.IterationCount.IntValue;

                byte[] data = ((Asn1OctetString)info.Content).GetOctets();

                byte[] mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, false, data);
                byte[] dig = dInfo.GetDigest();

                if (!Arrays.ConstantTimeAreEqual(mac, dig))
                {
                    if (password.Length > 0)
                    {
                        throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
                    }

                    // Try with incorrect zero length password
                    mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, true, data);

                    if (!Arrays.ConstantTimeAreEqual(mac, dig))
                    {
                        throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
                    }

                    wrongPkcs12Zero = true;
                }
            }

            keys.Clear();
            localIds.Clear();

            IList chain = Platform.CreateArrayList();

            if (info.ContentType.Equals(PkcsObjectIdentifiers.Data))
            {
                byte[]            octs     = ((Asn1OctetString)info.Content).GetOctets();
                AuthenticatedSafe authSafe = new AuthenticatedSafe(
                    (Asn1Sequence)Asn1OctetString.FromByteArray(octs));
                ContentInfo[] cis = authSafe.GetContentInfo();

                foreach (ContentInfo ci in cis)
                {
                    DerObjectIdentifier oid = ci.ContentType;

                    if (oid.Equals(PkcsObjectIdentifiers.Data))
                    {
                        byte[]       octets = ((Asn1OctetString)ci.Content).GetOctets();
                        Asn1Sequence seq    = (Asn1Sequence)Asn1Object.FromByteArray(octets);

                        foreach (Asn1Sequence subSeq in seq)
                        {
                            SafeBag b = new SafeBag(subSeq);

                            if (b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
                            {
                                EncryptedPrivateKeyInfo eIn      = EncryptedPrivateKeyInfo.GetInstance(b.BagValue);
                                PrivateKeyInfo          privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(
                                    password, wrongPkcs12Zero, eIn);
                                AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privInfo);

                                //
                                // set the attributes on the key
                                //
                                IDictionary        attributes = Platform.CreateHashtable();
                                AsymmetricKeyEntry pkcs12Key  = new AsymmetricKeyEntry(privKey, attributes);
                                string             alias      = null;
                                Asn1OctetString    localId    = null;

                                if (b.BagAttributes != null)
                                {
                                    foreach (Asn1Sequence sq in b.BagAttributes)
                                    {
                                        DerObjectIdentifier aOid    = (DerObjectIdentifier)sq[0];
                                        Asn1Set             attrSet = (Asn1Set)sq[1];
                                        Asn1Encodable       attr    = null;

                                        if (attrSet.Count > 0)
                                        {
                                            // TODO We should be adding all attributes in the set
                                            attr = attrSet[0];

                                            // TODO We might want to "merge" attribute sets with
                                            // the same OID - currently, differing values give an error
                                            if (attributes.Contains(aOid.Id))
                                            {
                                                // OK, but the value has to be the same
                                                if (!attributes[aOid.Id].Equals(attr))
                                                {
                                                    throw new IOException("attempt to add existing attribute with different value");
                                                }
                                            }
                                            else
                                            {
                                                attributes.Add(aOid.Id, attr);
                                            }

                                            if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
                                            {
                                                alias = ((DerBmpString)attr).GetString();
                                                // TODO Do these in a separate loop, just collect aliases here
                                                keys[alias] = pkcs12Key;
                                            }
                                            else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
                                            {
                                                localId = (Asn1OctetString)attr;
                                            }
                                        }
                                    }
                                }

                                if (localId != null)
                                {
                                    string name = Hex.ToHexString(localId.GetOctets());

                                    if (alias == null)
                                    {
                                        keys[name] = pkcs12Key;
                                    }
                                    else
                                    {
                                        // TODO There may have been more than one alias
                                        localIds[alias] = name;
                                    }
                                }
                                else
                                {
                                    unmarkedKey      = true;
                                    keys["unmarked"] = pkcs12Key;
                                }
                            }
                            else if (b.BagID.Equals(PkcsObjectIdentifiers.CertBag))
                            {
                                chain.Add(b);
                            }
                            else
                            {
                                Console.WriteLine("extra " + b.BagID);
                                Console.WriteLine("extra " + Asn1Dump.DumpAsString(b));
                            }
                        }
                    }
                    else if (oid.Equals(PkcsObjectIdentifiers.EncryptedData))
                    {
                        EncryptedData d      = EncryptedData.GetInstance(ci.Content);
                        byte[]        octets = CryptPbeData(false, d.EncryptionAlgorithm,
                                                            password, wrongPkcs12Zero, d.Content.GetOctets());
                        Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(octets);

                        foreach (Asn1Sequence subSeq in seq)
                        {
                            SafeBag b = new SafeBag(subSeq);

                            if (b.BagID.Equals(PkcsObjectIdentifiers.CertBag))
                            {
                                chain.Add(b);
                            }
                            else if (b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
                            {
                                EncryptedPrivateKeyInfo eIn      = EncryptedPrivateKeyInfo.GetInstance(b.BagValue);
                                PrivateKeyInfo          privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(
                                    password, wrongPkcs12Zero, eIn);
                                AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privInfo);

                                //
                                // set the attributes on the key
                                //
                                IDictionary        attributes = Platform.CreateHashtable();
                                AsymmetricKeyEntry pkcs12Key  = new AsymmetricKeyEntry(privKey, attributes);
                                string             alias      = null;
                                Asn1OctetString    localId    = null;

                                foreach (Asn1Sequence sq in b.BagAttributes)
                                {
                                    DerObjectIdentifier aOid    = (DerObjectIdentifier)sq[0];
                                    Asn1Set             attrSet = (Asn1Set)sq[1];
                                    Asn1Encodable       attr    = null;

                                    if (attrSet.Count > 0)
                                    {
                                        // TODO We should be adding all attributes in the set
                                        attr = attrSet[0];

                                        // TODO We might want to "merge" attribute sets with
                                        // the same OID - currently, differing values give an error
                                        if (attributes.Contains(aOid.Id))
                                        {
                                            // OK, but the value has to be the same
                                            if (!attributes[aOid.Id].Equals(attr))
                                            {
                                                throw new IOException("attempt to add existing attribute with different value");
                                            }
                                        }
                                        else
                                        {
                                            attributes.Add(aOid.Id, attr);
                                        }

                                        if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
                                        {
                                            alias = ((DerBmpString)attr).GetString();
                                            // TODO Do these in a separate loop, just collect aliases here
                                            keys[alias] = pkcs12Key;
                                        }
                                        else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
                                        {
                                            localId = (Asn1OctetString)attr;
                                        }
                                    }
                                }

                                // TODO Should we be checking localIds != null here
                                // as for PkcsObjectIdentifiers.Data version above?

                                string name = Hex.ToHexString(localId.GetOctets());

                                if (alias == null)
                                {
                                    keys[name] = pkcs12Key;
                                }
                                else
                                {
                                    // TODO There may have been more than one alias
                                    localIds[alias] = name;
                                }
                            }
                            else if (b.BagID.Equals(PkcsObjectIdentifiers.KeyBag))
                            {
                                PrivateKeyInfo         privKeyInfo = PrivateKeyInfo.GetInstance(b.BagValue);
                                AsymmetricKeyParameter privKey     = PrivateKeyFactory.CreateKey(privKeyInfo);

                                //
                                // set the attributes on the key
                                //
                                string             alias      = null;
                                Asn1OctetString    localId    = null;
                                IDictionary        attributes = Platform.CreateHashtable();
                                AsymmetricKeyEntry pkcs12Key  = new AsymmetricKeyEntry(privKey, attributes);

                                foreach (Asn1Sequence sq in b.BagAttributes)
                                {
                                    DerObjectIdentifier aOid    = DerObjectIdentifier.GetInstance(sq[0]);
                                    Asn1Set             attrSet = Asn1Set.GetInstance(sq[1]);
                                    Asn1Encodable       attr    = null;

                                    if (attrSet.Count > 0)
                                    {
                                        // TODO We should be adding all attributes in the set
                                        attr = attrSet[0];

                                        // TODO We might want to "merge" attribute sets with
                                        // the same OID - currently, differing values give an error
                                        if (attributes.Contains(aOid.Id))
                                        {
                                            // OK, but the value has to be the same
                                            if (!attributes[aOid.Id].Equals(attr))
                                            {
                                                throw new IOException("attempt to add existing attribute with different value");
                                            }
                                        }
                                        else
                                        {
                                            attributes.Add(aOid.Id, attr);
                                        }

                                        if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
                                        {
                                            alias = ((DerBmpString)attr).GetString();
                                            // TODO Do these in a separate loop, just collect aliases here
                                            keys[alias] = pkcs12Key;
                                        }
                                        else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
                                        {
                                            localId = (Asn1OctetString)attr;
                                        }
                                    }
                                }

                                // TODO Should we be checking localIds != null here
                                // as for PkcsObjectIdentifiers.Data version above?

                                string name = Hex.ToHexString(localId.GetOctets());

                                if (alias == null)
                                {
                                    keys[name] = pkcs12Key;
                                }
                                else
                                {
                                    // TODO There may have been more than one alias
                                    localIds[alias] = name;
                                }
                            }
                            else
                            {
                                Console.WriteLine("extra " + b.BagID);
                                Console.WriteLine("extra " + Asn1Dump.DumpAsString(b));
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("extra " + oid);
                        Console.WriteLine("extra " + Asn1Dump.DumpAsString(ci.Content));
                    }
                }
            }

            certs.Clear();
            chainCerts.Clear();
            keyCerts.Clear();

            foreach (SafeBag b in chain)
            {
                CertBag         cb     = new CertBag((Asn1Sequence)b.BagValue);
                byte[]          octets = ((Asn1OctetString)cb.CertValue).GetOctets();
                X509Certificate cert   = new X509CertificateParser().ReadCertificate(octets);

                //
                // set the attributes
                //
                IDictionary     attributes = Platform.CreateHashtable();
                Asn1OctetString localId    = null;
                string          alias      = null;

                if (b.BagAttributes != null)
                {
                    foreach (Asn1Sequence sq in b.BagAttributes)
                    {
                        DerObjectIdentifier aOid    = DerObjectIdentifier.GetInstance(sq[0]);
                        Asn1Set             attrSet = Asn1Set.GetInstance(sq[1]);

                        if (attrSet.Count > 0)
                        {
                            // TODO We should be adding all attributes in the set
                            Asn1Encodable attr = attrSet[0];

                            // TODO We might want to "merge" attribute sets with
                            // the same OID - currently, differing values give an error
                            if (attributes.Contains(aOid.Id))
                            {
                                // OK, but the value has to be the same
                                if (!attributes[aOid.Id].Equals(attr))
                                {
                                    throw new IOException("attempt to add existing attribute with different value");
                                }
                            }
                            else
                            {
                                attributes.Add(aOid.Id, attr);
                            }

                            if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
                            {
                                alias = ((DerBmpString)attr).GetString();
                            }
                            else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
                            {
                                localId = (Asn1OctetString)attr;
                            }
                        }
                    }
                }

                CertId certId = new CertId(cert.GetPublicKey());
                X509CertificateEntry pkcs12Cert = new X509CertificateEntry(cert, attributes);

                chainCerts[certId] = pkcs12Cert;

                if (unmarkedKey)
                {
                    if (keyCerts.Count == 0)
                    {
                        string name = Hex.ToHexString(certId.Id);

                        keyCerts[name] = pkcs12Cert;

                        object temp = keys["unmarked"];
                        keys.Remove("unmarked");
                        keys[name] = temp;
                    }
                }
                else
                {
                    if (localId != null)
                    {
                        string name = Hex.ToHexString(localId.GetOctets());

                        keyCerts[name] = pkcs12Cert;
                    }

                    if (alias != null)
                    {
                        // TODO There may have been more than one alias
                        certs[alias] = pkcs12Cert;
                    }
                }
            }
        }
예제 #2
0
        public void Load(
            Stream input,
            char[]      password)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            Asn1Sequence obj             = (Asn1Sequence)Asn1Object.FromStream(input);
            Pfx          bag             = new Pfx(obj);
            ContentInfo  info            = bag.AuthSafe;
            bool         wrongPkcs12Zero = false;

            if (password != null && bag.MacData != null) // check the mac code
            {
                MacData             mData = bag.MacData;
                DigestInfo          dInfo = mData.Mac;
                AlgorithmIdentifier algId = dInfo.AlgorithmID;
                byte[] salt    = mData.GetSalt();
                int    itCount = mData.IterationCount.IntValue;

                byte[] data = ((Asn1OctetString)info.Content).GetOctets();

                byte[] mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, false, data);
                byte[] dig = dInfo.GetDigest();

                if (!Arrays.ConstantTimeAreEqual(mac, dig))
                {
                    if (password.Length > 0)
                    {
                        throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
                    }

                    // Try with incorrect zero length password
                    mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, true, data);

                    if (!Arrays.ConstantTimeAreEqual(mac, dig))
                    {
                        throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
                    }

                    wrongPkcs12Zero = true;
                }
            }

            keys.Clear();
            localIds.Clear();
            unmarkedKeyEntry = null;

            IList certBags = Platform.CreateArrayList();

            if (info.ContentType.Equals(PkcsObjectIdentifiers.Data))
            {
                byte[]            octs     = ((Asn1OctetString)info.Content).GetOctets();
                AuthenticatedSafe authSafe = new AuthenticatedSafe(
                    (Asn1Sequence)Asn1OctetString.FromByteArray(octs));
                ContentInfo[] cis = authSafe.GetContentInfo();

                foreach (ContentInfo ci in cis)
                {
                    DerObjectIdentifier oid = ci.ContentType;

                    byte[] octets = null;
                    if (oid.Equals(PkcsObjectIdentifiers.Data))
                    {
                        octets = ((Asn1OctetString)ci.Content).GetOctets();
                    }
                    else if (oid.Equals(PkcsObjectIdentifiers.EncryptedData))
                    {
                        if (password != null)
                        {
                            EncryptedData d = EncryptedData.GetInstance(ci.Content);
                            octets = CryptPbeData(false, d.EncryptionAlgorithm,
                                                  password, wrongPkcs12Zero, d.Content.GetOctets());
                        }
                    }
                    else
                    {
                        // TODO Other data types
                    }

                    if (octets != null)
                    {
                        Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(octets);

                        foreach (Asn1Sequence subSeq in seq)
                        {
                            SafeBag b = new SafeBag(subSeq);

                            if (b.BagID.Equals(PkcsObjectIdentifiers.CertBag))
                            {
                                certBags.Add(b);
                            }
                            else if (b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
                            {
                                LoadPkcs8ShroudedKeyBag(EncryptedPrivateKeyInfo.GetInstance(b.BagValue),
                                                        b.BagAttributes, password, wrongPkcs12Zero);
                            }
                            else if (b.BagID.Equals(PkcsObjectIdentifiers.KeyBag))
                            {
                                LoadKeyBag(PrivateKeyInfo.GetInstance(b.BagValue), b.BagAttributes);
                            }
                            else
                            {
                                // TODO Other bag types
                            }
                        }
                    }
                }
            }

            certs.Clear();
            chainCerts.Clear();
            keyCerts.Clear();

            foreach (SafeBag b in certBags)
            {
                CertBag         certBag = new CertBag((Asn1Sequence)b.BagValue);
                byte[]          octets  = ((Asn1OctetString)certBag.CertValue).GetOctets();
                X509Certificate cert    = new X509CertificateParser().ReadCertificate(octets);

                //
                // set the attributes
                //
                IDictionary     attributes = Platform.CreateHashtable();
                Asn1OctetString localId    = null;
                string          alias      = null;

                if (b.BagAttributes != null)
                {
                    foreach (Asn1Sequence sq in b.BagAttributes)
                    {
                        DerObjectIdentifier aOid    = DerObjectIdentifier.GetInstance(sq[0]);
                        Asn1Set             attrSet = Asn1Set.GetInstance(sq[1]);

                        if (attrSet.Count > 0)
                        {
                            // TODO We should be adding all attributes in the set
                            Asn1Encodable attr = attrSet[0];

                            // TODO We might want to "merge" attribute sets with
                            // the same OID - currently, differing values give an error
                            if (attributes.Contains(aOid.Id))
                            {
                                // OK, but the value has to be the same
                                if (!attributes[aOid.Id].Equals(attr))
                                {
                                    throw new IOException("attempt to add existing attribute with different value");
                                }
                            }
                            else
                            {
                                attributes.Add(aOid.Id, attr);
                            }

                            if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
                            {
                                alias = ((DerBmpString)attr).GetString();
                            }
                            else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
                            {
                                localId = (Asn1OctetString)attr;
                            }
                        }
                    }
                }

                CertId certId = new CertId(cert.GetPublicKey());
                X509CertificateEntry certEntry = new X509CertificateEntry(cert, attributes);

                chainCerts[certId] = certEntry;

                if (unmarkedKeyEntry != null)
                {
                    if (keyCerts.Count == 0)
                    {
                        string name = Hex.ToHexString(certId.Id);

                        keyCerts[name] = certEntry;
                        keys[name]     = unmarkedKeyEntry;
                    }
                }
                else
                {
                    if (localId != null)
                    {
                        string name = Hex.ToHexString(localId.GetOctets());

                        keyCerts[name] = certEntry;
                    }

                    if (alias != null)
                    {
                        // TODO There may have been more than one alias
                        certs[alias] = certEntry;
                    }
                }
            }
        }
예제 #3
0
        public void Load(Stream input, char[] password)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            Asn1Sequence seq             = (Asn1Sequence)Asn1Object.FromStream(input);
            Pfx          pfx             = new Pfx(seq);
            ContentInfo  authSafe        = pfx.AuthSafe;
            bool         wrongPkcs12Zero = false;

            if (password != null && pfx.MacData != null)
            {
                MacData             macData     = pfx.MacData;
                DigestInfo          mac         = macData.Mac;
                AlgorithmIdentifier algorithmID = mac.AlgorithmID;
                byte[] salt     = macData.GetSalt();
                int    intValue = macData.IterationCount.IntValue;
                byte[] octets   = ((Asn1OctetString)authSafe.Content).GetOctets();
                byte[] a        = Pkcs12Store.CalculatePbeMac(algorithmID.ObjectID, salt, intValue, password, false, octets);
                byte[] digest   = mac.GetDigest();
                if (!Arrays.ConstantTimeAreEqual(a, digest))
                {
                    if (password.Length > 0)
                    {
                        throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
                    }
                    a = Pkcs12Store.CalculatePbeMac(algorithmID.ObjectID, salt, intValue, password, true, octets);
                    if (!Arrays.ConstantTimeAreEqual(a, digest))
                    {
                        throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
                    }
                    wrongPkcs12Zero = true;
                }
            }
            this.keys.Clear();
            this.localIds.Clear();
            this.unmarkedKeyEntry = null;
            IList list = Platform.CreateArrayList();

            if (authSafe.ContentType.Equals(PkcsObjectIdentifiers.Data))
            {
                byte[]            octets2           = ((Asn1OctetString)authSafe.Content).GetOctets();
                AuthenticatedSafe authenticatedSafe = new AuthenticatedSafe((Asn1Sequence)Asn1Object.FromByteArray(octets2));
                ContentInfo[]     contentInfo       = authenticatedSafe.GetContentInfo();
                ContentInfo[]     array             = contentInfo;
                for (int i = 0; i < array.Length; i++)
                {
                    ContentInfo         contentInfo2 = array[i];
                    DerObjectIdentifier contentType  = contentInfo2.ContentType;
                    byte[] array2 = null;
                    if (contentType.Equals(PkcsObjectIdentifiers.Data))
                    {
                        array2 = ((Asn1OctetString)contentInfo2.Content).GetOctets();
                    }
                    else if (contentType.Equals(PkcsObjectIdentifiers.EncryptedData) && password != null)
                    {
                        EncryptedData instance = EncryptedData.GetInstance(contentInfo2.Content);
                        array2 = Pkcs12Store.CryptPbeData(false, instance.EncryptionAlgorithm, password, wrongPkcs12Zero, instance.Content.GetOctets());
                    }
                    if (array2 != null)
                    {
                        Asn1Sequence asn1Sequence = (Asn1Sequence)Asn1Object.FromByteArray(array2);
                        foreach (Asn1Sequence seq2 in asn1Sequence)
                        {
                            SafeBag safeBag = new SafeBag(seq2);
                            if (safeBag.BagID.Equals(PkcsObjectIdentifiers.CertBag))
                            {
                                list.Add(safeBag);
                            }
                            else if (safeBag.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
                            {
                                this.LoadPkcs8ShroudedKeyBag(EncryptedPrivateKeyInfo.GetInstance(safeBag.BagValue), safeBag.BagAttributes, password, wrongPkcs12Zero);
                            }
                            else if (safeBag.BagID.Equals(PkcsObjectIdentifiers.KeyBag))
                            {
                                this.LoadKeyBag(PrivateKeyInfo.GetInstance(safeBag.BagValue), safeBag.BagAttributes);
                            }
                        }
                    }
                }
            }
            this.certs.Clear();
            this.chainCerts.Clear();
            this.keyCerts.Clear();
            foreach (SafeBag safeBag2 in list)
            {
                CertBag         certBag         = new CertBag((Asn1Sequence)safeBag2.BagValue);
                byte[]          octets3         = ((Asn1OctetString)certBag.CertValue).GetOctets();
                X509Certificate x509Certificate = new X509CertificateParser().ReadCertificate(octets3);
                IDictionary     dictionary      = Platform.CreateHashtable();
                Asn1OctetString asn1OctetString = null;
                string          text            = null;
                if (safeBag2.BagAttributes != null)
                {
                    foreach (Asn1Sequence asn1Sequence2 in safeBag2.BagAttributes)
                    {
                        DerObjectIdentifier instance2 = DerObjectIdentifier.GetInstance(asn1Sequence2[0]);
                        Asn1Set             instance3 = Asn1Set.GetInstance(asn1Sequence2[1]);
                        if (instance3.Count > 0)
                        {
                            Asn1Encodable asn1Encodable = instance3[0];
                            if (dictionary.Contains(instance2.Id))
                            {
                                if (!dictionary[instance2.Id].Equals(asn1Encodable))
                                {
                                    throw new IOException("attempt to add existing attribute with different value");
                                }
                            }
                            else
                            {
                                dictionary.Add(instance2.Id, asn1Encodable);
                            }
                            if (instance2.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
                            {
                                text = ((DerBmpString)asn1Encodable).GetString();
                            }
                            else if (instance2.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
                            {
                                asn1OctetString = (Asn1OctetString)asn1Encodable;
                            }
                        }
                    }
                }
                Pkcs12Store.CertId   certId = new Pkcs12Store.CertId(x509Certificate.GetPublicKey());
                X509CertificateEntry value  = new X509CertificateEntry(x509Certificate, dictionary);
                this.chainCerts[certId] = value;
                if (this.unmarkedKeyEntry != null)
                {
                    if (this.keyCerts.Count == 0)
                    {
                        string text2 = Hex.ToHexString(certId.Id);
                        this.keyCerts[text2] = value;
                        this.keys[text2]     = this.unmarkedKeyEntry;
                    }
                }
                else
                {
                    if (asn1OctetString != null)
                    {
                        string key = Hex.ToHexString(asn1OctetString.GetOctets());
                        this.keyCerts[key] = value;
                    }
                    if (text != null)
                    {
                        this.certs[text] = value;
                    }
                }
            }
        }
예제 #4
0
        public void Save(
            Stream stream,
            char[]                  password,
            SecureRandom random)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (password == null)
            {
                throw new ArgumentNullException("password");
            }
            if (random == null)
            {
                throw new ArgumentNullException("random");
            }

            //
            // handle the key
            //
            Asn1EncodableVector keyS = new Asn1EncodableVector();

            foreach (string name in keys.Keys)
            {
                byte[] kSalt = new byte[SaltSize];
                random.NextBytes(kSalt);

                AsymmetricKeyEntry      privKey = (AsymmetricKeyEntry)keys[name];
                EncryptedPrivateKeyInfo kInfo   =
                    EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
                        keyAlgorithm, password, kSalt, MinIterations, privKey.Key);

                Asn1EncodableVector kName = new Asn1EncodableVector();

                foreach (string oid in privKey.BagAttributeKeys)
                {
                    Asn1Encodable entry = privKey[oid];

                    // NB: Ignore any existing FriendlyName
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        continue;
                    }

                    kName.Add(
                        new DerSequence(
                            new DerObjectIdentifier(oid),
                            new DerSet(entry)));
                }

                //
                // make sure we are using the local alias on store
                //
                // NB: We always set the FriendlyName based on 'name'
                //if (privKey[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
                {
                    kName.Add(
                        new DerSequence(
                            PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
                            new DerSet(new DerBmpString(name))));
                }

                //
                // make sure we have a local key-id
                //
                if (privKey[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
                {
                    X509CertificateEntry   ct           = GetCertificate(name);
                    AsymmetricKeyParameter pubKey       = ct.Certificate.GetPublicKey();
                    SubjectKeyIdentifier   subjectKeyID = CreateSubjectKeyID(pubKey);

                    kName.Add(
                        new DerSequence(
                            PkcsObjectIdentifiers.Pkcs9AtLocalKeyID,
                            new DerSet(subjectKeyID)));
                }

                SafeBag kBag = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, kInfo.ToAsn1Object(), new DerSet(kName));
                keyS.Add(kBag);
            }

            byte[] derEncodedBytes = new DerSequence(keyS).GetDerEncoded();

            BerOctetString keyString = new BerOctetString(derEncodedBytes);

            //
            // certificate processing
            //
            byte[] cSalt = new byte[SaltSize];

            random.NextBytes(cSalt);

            Asn1EncodableVector certSeq = new Asn1EncodableVector();
            Pkcs12PbeParams     cParams = new Pkcs12PbeParams(cSalt, MinIterations);
            AlgorithmIdentifier cAlgId  = new AlgorithmIdentifier(certAlgorithm, cParams.ToAsn1Object());
            ISet doneCerts = new HashSet();

            foreach (string name in keys.Keys)
            {
                X509CertificateEntry certEntry = GetCertificate(name);
                CertBag cBag = new CertBag(
                    PkcsObjectIdentifiers.X509Certificate,
                    new DerOctetString(certEntry.Certificate.GetEncoded()));

                Asn1EncodableVector fName = new Asn1EncodableVector();

                foreach (string oid in certEntry.BagAttributeKeys)
                {
                    Asn1Encodable entry = certEntry[oid];

                    // NB: Ignore any existing FriendlyName
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        continue;
                    }

                    fName.Add(
                        new DerSequence(
                            new DerObjectIdentifier(oid),
                            new DerSet(entry)));
                }

                //
                // make sure we are using the local alias on store
                //
                // NB: We always set the FriendlyName based on 'name'
                //if (certEntry[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
                {
                    fName.Add(
                        new DerSequence(
                            PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
                            new DerSet(new DerBmpString(name))));
                }

                //
                // make sure we have a local key-id
                //
                if (certEntry[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
                {
                    AsymmetricKeyParameter pubKey       = certEntry.Certificate.GetPublicKey();
                    SubjectKeyIdentifier   subjectKeyID = CreateSubjectKeyID(pubKey);

                    fName.Add(
                        new DerSequence(
                            PkcsObjectIdentifiers.Pkcs9AtLocalKeyID,
                            new DerSet(subjectKeyID)));
                }

                SafeBag sBag = new SafeBag(
                    PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName));

                certSeq.Add(sBag);

                doneCerts.Add(certEntry.Certificate);
            }

            foreach (string certId in certs.Keys)
            {
                X509CertificateEntry cert = (X509CertificateEntry)certs[certId];

                if (keys[certId] != null)
                {
                    continue;
                }

                CertBag cBag = new CertBag(
                    PkcsObjectIdentifiers.X509Certificate,
                    new DerOctetString(cert.Certificate.GetEncoded()));

                Asn1EncodableVector fName = new Asn1EncodableVector();

                foreach (string oid in cert.BagAttributeKeys)
                {
                    // a certificate not immediately linked to a key doesn't require
                    // a localKeyID and will confuse some PKCS12 implementations.
                    //
                    // If we find one, we'll prune it out.
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
                    {
                        continue;
                    }

                    Asn1Encodable entry = cert[oid];

                    // NB: Ignore any existing FriendlyName
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        continue;
                    }

                    fName.Add(
                        new DerSequence(
                            new DerObjectIdentifier(oid),
                            new DerSet(entry)));
                }

                //
                // make sure we are using the local alias on store
                //
                // NB: We always set the FriendlyName based on 'certId'
                //if (cert[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
                {
                    fName.Add(
                        new DerSequence(
                            PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
                            new DerSet(new DerBmpString(certId))));
                }

                SafeBag sBag = new SafeBag(PkcsObjectIdentifiers.CertBag,
                                           cBag.ToAsn1Object(), new DerSet(fName));

                certSeq.Add(sBag);

                doneCerts.Add(cert.Certificate);
            }

            foreach (CertId certId in chainCerts.Keys)
            {
                X509CertificateEntry cert = (X509CertificateEntry)chainCerts[certId];

                if (doneCerts.Contains(cert.Certificate))
                {
                    continue;
                }

                CertBag cBag = new CertBag(
                    PkcsObjectIdentifiers.X509Certificate,
                    new DerOctetString(cert.Certificate.GetEncoded()));

                Asn1EncodableVector fName = new Asn1EncodableVector();

                foreach (string oid in cert.BagAttributeKeys)
                {
                    // a certificate not immediately linked to a key doesn't require
                    // a localKeyID and will confuse some PKCS12 implementations.
                    //
                    // If we find one, we'll prune it out.
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
                    {
                        continue;
                    }

                    fName.Add(
                        new DerSequence(
                            new DerObjectIdentifier(oid),
                            new DerSet(cert[oid])));
                }

                SafeBag sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName));

                certSeq.Add(sBag);
            }

            derEncodedBytes = new DerSequence(certSeq).GetDerEncoded();

            byte[] certBytes = CryptPbeData(true, cAlgId, password, false, derEncodedBytes);

            EncryptedData cInfo = new EncryptedData(PkcsObjectIdentifiers.Data, cAlgId, new BerOctetString(certBytes));

            ContentInfo[] info = new ContentInfo[]
            {
                new ContentInfo(PkcsObjectIdentifiers.Data, keyString),
                new ContentInfo(PkcsObjectIdentifiers.EncryptedData, cInfo.ToAsn1Object())
            };

            byte[] data = new AuthenticatedSafe(info).GetEncoded();

            ContentInfo mainInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(data));

            //
            // create the mac
            //
            byte[] mSalt = new byte[20];
            random.NextBytes(mSalt);

            byte[] mac = CalculatePbeMac(OiwObjectIdentifiers.IdSha1,
                                         mSalt, MinIterations, password, false, data);

            AlgorithmIdentifier algId = new AlgorithmIdentifier(
                OiwObjectIdentifiers.IdSha1, DerNull.Instance);
            DigestInfo dInfo = new DigestInfo(algId, mac);

            MacData mData = new MacData(dInfo, mSalt, MinIterations);

            //
            // output the Pfx
            //
            Pfx pfx = new Pfx(mainInfo, mData);

            BerOutputStream berOut = new BerOutputStream(stream);

            berOut.WriteObject(pfx);
        }