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
                            {
                                //System.Diagnostics.Debug.WriteLine("extra " + b.BagID);
                                //System.Diagnostics.Debug.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)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
                            {
                                System.Diagnostics.Debug.WriteLine("extra " + b.BagID);
                                System.Diagnostics.Debug.WriteLine("extra " + Asn1Dump.DumpAsString(b));
                            }
                        }
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("extra " + oid);
                        System.Diagnostics.Debug.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)sq[0];
                        Asn1Set             attrSet = (Asn1Set)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;
                    }
                }
            }
        }
Example #2
0
 public static PrivateKeyInfo CreatePrivateKeyInfo(char[] passPhrase, EncryptedPrivateKeyInfo encInfo)
 {
     return(PrivateKeyInfoFactory.CreatePrivateKeyInfo(passPhrase, false, encInfo));
 }
Example #3
0
        public void Save(
            Stream stream,
            char[]                      password,
            SecureRandom random)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (random == null)
            {
                throw new ArgumentNullException("random");
            }

            //
            // handle the keys
            //
            Asn1EncodableVector keyBags = new Asn1EncodableVector();

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

                AsymmetricKeyEntry privKey = (AsymmetricKeyEntry)keys[name];

                DerObjectIdentifier bagOid;
                Asn1Encodable       bagData;

                if (password == null)
                {
                    bagOid  = PkcsObjectIdentifiers.KeyBag;
                    bagData = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privKey.Key);
                }
                else
                {
                    bagOid  = PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag;
                    bagData = 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)));
                }

                keyBags.Add(new SafeBag(bagOid, bagData.ToAsn1Object(), new DerSet(kName)));
            }

            byte[]      keyBagsEncoding = new DerSequence(keyBags).GetDerEncoded();
            ContentInfo keysInfo        = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(keyBagsEncoding));

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

            random.NextBytes(cSalt);

            Asn1EncodableVector certBags = 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)));
                }

                certBags.Add(new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName)));

                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))));
                }

                certBags.Add(new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName)));

                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])));
                }

                certBags.Add(new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName)));
            }

            byte[] certBagsEncoding = new DerSequence(certBags).GetDerEncoded();

            ContentInfo certsInfo;

            if (password == null)
            {
                certsInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(certBagsEncoding));
            }
            else
            {
                byte[]        certBytes = CryptPbeData(true, cAlgId, password, false, certBagsEncoding);
                EncryptedData cInfo     = new EncryptedData(PkcsObjectIdentifiers.Data, cAlgId, new BerOctetString(certBytes));
                certsInfo = new ContentInfo(PkcsObjectIdentifiers.EncryptedData, cInfo.ToAsn1Object());
            }

            ContentInfo[] info = new ContentInfo[] { keysInfo, certsInfo };

            byte[] data = new AuthenticatedSafe(info).GetEncoded(
                useDerEncoding ? Asn1Encodable.Der : Asn1Encodable.Ber);

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

            //
            // create the mac
            //
            MacData macData = null;

            if (password != null)
            {
                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 = new MacData(dInfo, mSalt, MinIterations);
            }

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

            DerOutputStream derOut;

            if (useDerEncoding)
            {
                derOut = new DerOutputStream(stream);
            }
            else
            {
                derOut = new BerOutputStream(stream);
            }

            derOut.WriteObject(pfx);
        }
Example #4
0
        public void Save(Stream stream, char[] password, SecureRandom random)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (random == null)
            {
                throw new ArgumentNullException("random");
            }
            Asn1EncodableVector asn1EncodableVector = new Asn1EncodableVector(new Asn1Encodable[0]);

            foreach (string text in this.keys.Keys)
            {
                byte[] array = new byte[20];
                random.NextBytes(array);
                AsymmetricKeyEntry  asymmetricKeyEntry = (AsymmetricKeyEntry)this.keys[text];
                DerObjectIdentifier oid;
                Asn1Encodable       asn1Encodable;
                if (password == null)
                {
                    oid           = PkcsObjectIdentifiers.KeyBag;
                    asn1Encodable = PrivateKeyInfoFactory.CreatePrivateKeyInfo(asymmetricKeyEntry.Key);
                }
                else
                {
                    oid           = PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag;
                    asn1Encodable = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(this.keyAlgorithm, password, array, 1024, asymmetricKeyEntry.Key);
                }
                Asn1EncodableVector asn1EncodableVector2 = new Asn1EncodableVector(new Asn1Encodable[0]);
                foreach (string text2 in asymmetricKeyEntry.BagAttributeKeys)
                {
                    Asn1Encodable obj = asymmetricKeyEntry[text2];
                    if (!text2.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        asn1EncodableVector2.Add(new Asn1Encodable[]
                        {
                            new DerSequence(new Asn1Encodable[]
                            {
                                new DerObjectIdentifier(text2),
                                new DerSet(obj)
                            })
                        });
                    }
                }
                asn1EncodableVector2.Add(new Asn1Encodable[]
                {
                    new DerSequence(new Asn1Encodable[]
                    {
                        PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
                        new DerSet(new DerBmpString(text))
                    })
                });
                if (asymmetricKeyEntry[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
                {
                    X509CertificateEntry   certificate = this.GetCertificate(text);
                    AsymmetricKeyParameter publicKey   = certificate.Certificate.GetPublicKey();
                    SubjectKeyIdentifier   obj2        = Pkcs12Store.CreateSubjectKeyID(publicKey);
                    asn1EncodableVector2.Add(new Asn1Encodable[]
                    {
                        new DerSequence(new Asn1Encodable[]
                        {
                            PkcsObjectIdentifiers.Pkcs9AtLocalKeyID,
                            new DerSet(obj2)
                        })
                    });
                }
                asn1EncodableVector.Add(new Asn1Encodable[]
                {
                    new SafeBag(oid, asn1Encodable.ToAsn1Object(), new DerSet(asn1EncodableVector2))
                });
            }
            byte[]      derEncoded  = new DerSequence(asn1EncodableVector).GetDerEncoded();
            ContentInfo contentInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(derEncoded));

            byte[] array2 = new byte[20];
            random.NextBytes(array2);
            Asn1EncodableVector asn1EncodableVector3 = new Asn1EncodableVector(new Asn1Encodable[0]);
            Pkcs12PbeParams     pkcs12PbeParams      = new Pkcs12PbeParams(array2, 1024);
            AlgorithmIdentifier algorithmIdentifier  = new AlgorithmIdentifier(this.certAlgorithm, pkcs12PbeParams.ToAsn1Object());
            ISet set = new HashSet();

            foreach (string text3 in this.keys.Keys)
            {
                X509CertificateEntry certificate2        = this.GetCertificate(text3);
                CertBag             certBag              = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(certificate2.Certificate.GetEncoded()));
                Asn1EncodableVector asn1EncodableVector4 = new Asn1EncodableVector(new Asn1Encodable[0]);
                foreach (string text4 in certificate2.BagAttributeKeys)
                {
                    Asn1Encodable obj3 = certificate2[text4];
                    if (!text4.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        asn1EncodableVector4.Add(new Asn1Encodable[]
                        {
                            new DerSequence(new Asn1Encodable[]
                            {
                                new DerObjectIdentifier(text4),
                                new DerSet(obj3)
                            })
                        });
                    }
                }
                asn1EncodableVector4.Add(new Asn1Encodable[]
                {
                    new DerSequence(new Asn1Encodable[]
                    {
                        PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
                        new DerSet(new DerBmpString(text3))
                    })
                });
                if (certificate2[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
                {
                    AsymmetricKeyParameter publicKey2 = certificate2.Certificate.GetPublicKey();
                    SubjectKeyIdentifier   obj4       = Pkcs12Store.CreateSubjectKeyID(publicKey2);
                    asn1EncodableVector4.Add(new Asn1Encodable[]
                    {
                        new DerSequence(new Asn1Encodable[]
                        {
                            PkcsObjectIdentifiers.Pkcs9AtLocalKeyID,
                            new DerSet(obj4)
                        })
                    });
                }
                asn1EncodableVector3.Add(new Asn1Encodable[]
                {
                    new SafeBag(PkcsObjectIdentifiers.CertBag, certBag.ToAsn1Object(), new DerSet(asn1EncodableVector4))
                });
                set.Add(certificate2.Certificate);
            }
            foreach (string text5 in this.certs.Keys)
            {
                X509CertificateEntry x509CertificateEntry = (X509CertificateEntry)this.certs[text5];
                if (this.keys[text5] == null)
                {
                    CertBag             certBag2             = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(x509CertificateEntry.Certificate.GetEncoded()));
                    Asn1EncodableVector asn1EncodableVector5 = new Asn1EncodableVector(new Asn1Encodable[0]);
                    foreach (string text6 in x509CertificateEntry.BagAttributeKeys)
                    {
                        if (!text6.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
                        {
                            Asn1Encodable obj5 = x509CertificateEntry[text6];
                            if (!text6.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                            {
                                asn1EncodableVector5.Add(new Asn1Encodable[]
                                {
                                    new DerSequence(new Asn1Encodable[]
                                    {
                                        new DerObjectIdentifier(text6),
                                        new DerSet(obj5)
                                    })
                                });
                            }
                        }
                    }
                    asn1EncodableVector5.Add(new Asn1Encodable[]
                    {
                        new DerSequence(new Asn1Encodable[]
                        {
                            PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
                            new DerSet(new DerBmpString(text5))
                        })
                    });
                    asn1EncodableVector3.Add(new Asn1Encodable[]
                    {
                        new SafeBag(PkcsObjectIdentifiers.CertBag, certBag2.ToAsn1Object(), new DerSet(asn1EncodableVector5))
                    });
                    set.Add(x509CertificateEntry.Certificate);
                }
            }
            foreach (Pkcs12Store.CertId key in this.chainCerts.Keys)
            {
                X509CertificateEntry x509CertificateEntry2 = (X509CertificateEntry)this.chainCerts[key];
                if (!set.Contains(x509CertificateEntry2.Certificate))
                {
                    CertBag             certBag3             = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(x509CertificateEntry2.Certificate.GetEncoded()));
                    Asn1EncodableVector asn1EncodableVector6 = new Asn1EncodableVector(new Asn1Encodable[0]);
                    foreach (string text7 in x509CertificateEntry2.BagAttributeKeys)
                    {
                        if (!text7.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
                        {
                            asn1EncodableVector6.Add(new Asn1Encodable[]
                            {
                                new DerSequence(new Asn1Encodable[]
                                {
                                    new DerObjectIdentifier(text7),
                                    new DerSet(x509CertificateEntry2[text7])
                                })
                            });
                        }
                    }
                    asn1EncodableVector3.Add(new Asn1Encodable[]
                    {
                        new SafeBag(PkcsObjectIdentifiers.CertBag, certBag3.ToAsn1Object(), new DerSet(asn1EncodableVector6))
                    });
                }
            }
            byte[]      derEncoded2 = new DerSequence(asn1EncodableVector3).GetDerEncoded();
            ContentInfo contentInfo2;

            if (password == null)
            {
                contentInfo2 = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(derEncoded2));
            }
            else
            {
                byte[]        str           = Pkcs12Store.CryptPbeData(true, algorithmIdentifier, password, false, derEncoded2);
                EncryptedData encryptedData = new EncryptedData(PkcsObjectIdentifiers.Data, algorithmIdentifier, new BerOctetString(str));
                contentInfo2 = new ContentInfo(PkcsObjectIdentifiers.EncryptedData, encryptedData.ToAsn1Object());
            }
            ContentInfo[] info = new ContentInfo[]
            {
                contentInfo,
                contentInfo2
            };
            byte[]      encoded      = new AuthenticatedSafe(info).GetEncoded(this.useDerEncoding ? "DER" : "BER");
            ContentInfo contentInfo3 = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(encoded));
            MacData     macData      = null;

            if (password != null)
            {
                byte[] array3 = new byte[20];
                random.NextBytes(array3);
                byte[] digest               = Pkcs12Store.CalculatePbeMac(OiwObjectIdentifiers.IdSha1, array3, 1024, password, false, encoded);
                AlgorithmIdentifier algID   = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
                DigestInfo          digInfo = new DigestInfo(algID, digest);
                macData = new MacData(digInfo, array3, 1024);
            }
            Pfx             obj6 = new Pfx(contentInfo3, macData);
            DerOutputStream derOutputStream;

            if (this.useDerEncoding)
            {
                derOutputStream = new DerOutputStream(stream);
            }
            else
            {
                derOutputStream = new BerOutputStream(stream);
            }
            derOutputStream.WriteObject(obj6);
        }