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); IAsymmetricKeyParameter 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) { IAsymmetricKeyParameter 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( useDerEncoding ? Asn1Encodable.Der : Asn1Encodable.Ber); 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); DerOutputStream derOut; if (useDerEncoding) { derOut = new DerOutputStream(stream); } else { derOut = new BerOutputStream(stream); } derOut.WriteObject(pfx); }
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"); } ContentInfo[] c = new ContentInfo[2]; // // 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) { kName.Add( new DerSequence( new DerObjectIdentifier(oid), new DerSet(privKey[oid]))); } // // make sure we have a local key-id // if (privKey[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null) { X509CertificateEntry ct = GetCertificate(name); SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo( ct.Certificate.GetPublicKey()); kName.Add( new DerSequence( PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, new DerSet(new SubjectKeyIdentifier(info)))); } // // make sure we are using the local alias on store // DerBmpString nm = (DerBmpString)privKey[PkcsObjectIdentifiers.Pkcs9AtFriendlyName]; if (nm == null || !nm.GetString().Equals(name)) { kName.Add( new DerSequence( PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(name)))); } 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()); Hashtable doneCerts = new Hashtable(); foreach (string name in keys.Keys) { X509CertificateEntry certEntry = GetCertificate(name); CertBag cBag = new CertBag( PkcsObjectIdentifiers.X509CertType, new DerOctetString(certEntry.Certificate.GetEncoded())); Asn1EncodableVector fName = new Asn1EncodableVector(); foreach (string oid in certEntry.BagAttributeKeys) { fName.Add( new DerSequence( new DerObjectIdentifier(oid), new DerSet(certEntry[oid]))); } // // make sure we are using the local alias on store // DerBmpString nm = (DerBmpString)certEntry[PkcsObjectIdentifiers.Pkcs9AtFriendlyName]; if (nm == null || !nm.GetString().Equals(name)) { fName.Add( new DerSequence( PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(name)))); } // // make sure we have a local key-id // if (certEntry[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null) { SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo( certEntry.Certificate.GetPublicKey()); fName.Add( new DerSequence( PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, new DerSet(new SubjectKeyIdentifier(info)))); } SafeBag sBag = new SafeBag( PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName)); certSeq.Add(sBag); doneCerts.Add(certEntry.Certificate, certEntry.Certificate); } foreach (string certId in certs.Keys) { X509CertificateEntry cert = (X509CertificateEntry)certs[certId]; if (keys[certId] != null) { continue; } CertBag cBag = new CertBag( PkcsObjectIdentifiers.X509CertType, new DerOctetString(cert.Certificate.GetEncoded())); Asn1EncodableVector fName = new Asn1EncodableVector(); foreach (string oid in cert.BagAttributeKeys) { fName.Add( new DerSequence( new DerObjectIdentifier(oid), new DerSet(cert[oid]))); } // // make sure we are using the local alias on store // DerBmpString nm = (DerBmpString)cert[PkcsObjectIdentifiers.Pkcs9AtFriendlyName]; if (nm == null || !nm.GetString().Equals(certId)) { 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, cert); } foreach (CertId certId in chainCerts.Keys) { X509CertificateEntry cert = (X509CertificateEntry)chainCerts[certId]; if (doneCerts[cert] != null) { continue; } CertBag cBag = new CertBag( PkcsObjectIdentifiers.X509CertType, new DerOctetString(cert.Certificate.GetEncoded())); Asn1EncodableVector fName = new Asn1EncodableVector(); foreach (string oid in cert.BagAttributeKeys) { 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 = EncryptData(new AlgorithmIdentifier(certAlgorithm, cParams), derEncodedBytes, password); EncryptedData cInfo = new EncryptedData(PkcsObjectIdentifiers.Data, cAlgId, new BerOctetString(certBytes)); c[0] = new ContentInfo(PkcsObjectIdentifiers.Data, keyString); c[1] = new ContentInfo(PkcsObjectIdentifiers.EncryptedData, cInfo.ToAsn1Object()); AuthenticatedSafe auth = new AuthenticatedSafe(c); byte[] pkg = auth.GetEncoded(); ContentInfo mainInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(pkg)); // // create the mac // byte[] mSalt = new byte[20]; int itCount = minIterations; random.NextBytes(mSalt); byte[] data = ((Asn1OctetString)mainInfo.Content).GetOctets(); MacData mData = null; Asn1Encodable parameters = PbeUtilities.GenerateAlgorithmParameters(OiwObjectIdentifiers.IdSha1, mSalt, itCount); ICipherParameters keyParameters = PbeUtilities.GenerateCipherParameters( OiwObjectIdentifiers.IdSha1, password, parameters); IMac mac = (IMac)PbeUtilities.CreateEngine(OiwObjectIdentifiers.IdSha1); mac.Init(keyParameters); mac.BlockUpdate(data, 0, data.Length); byte[] res = new byte[mac.GetMacSize()]; mac.DoFinal(res, 0); AlgorithmIdentifier algId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance); DigestInfo dInfo = new DigestInfo(algId, res); mData = new MacData(dInfo, mSalt, itCount); // // output the Pfx // Pfx pfx = new Pfx(mainInfo, mData); BerOutputStream berOut = new BerOutputStream(stream); berOut.WriteObject(pfx); }
public static void Save(this Pkcs12Store store, Stream stream, string encryptionPassword, string integrityPassword, SecureRandom random) { const int saltSize = 20; const int minIterations = 1024; if (stream == null) { throw new ArgumentNullException("stream"); } //if (null != encryptionPassword && encryptionPassword == integrityPassword) //{ // store.Save(stream, encryptionPassword.ToArray(), random); // return; //} if (random == null) { throw new ArgumentNullException("random"); } var T = store.GetType(); Func <AsymmetricKeyParameter, SubjectKeyIdentifier> CreateSubjectKeyID = (pubKey_) => { var method = T.GetMethod("CreateSubjectKeyID", BindingFlags.NonPublic | BindingFlags.Static); return((SubjectKeyIdentifier)method.Invoke(store, new object[] { pubKey_ })); }; Func <DerObjectIdentifier> keyAlgorithm = () => { var property = T.GetField("keyAlgorithm", BindingFlags.NonPublic | BindingFlags.Instance); return((DerObjectIdentifier)property.GetValue(store)); }; Func <DerObjectIdentifier> certAlgorithm = () => { var property = T.GetField("certAlgorithm", BindingFlags.NonPublic | BindingFlags.Instance); return((DerObjectIdentifier)property.GetValue(store)); }; // // handle the key // Asn1EncodableVector keyS = new Asn1EncodableVector(); var keys = store.Aliases.OfType <string>().ToDictionary(alias => alias, store.GetKey); foreach (string name in store.Aliases.OfType <string>()) { byte[] kSalt = new byte[saltSize]; random.NextBytes(kSalt); AsymmetricKeyEntry privKey = keys[name]; Asn1Encodable kInfo = null; if (!string.IsNullOrEmpty(encryptionPassword)) { kInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(keyAlgorithm(), encryptionPassword.ToArray(), kSalt, minIterations, privKey.Key); } else { kInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(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 = store.GetCertificate(name); AsymmetricKeyParameter pubKey = ct.Certificate.GetPublicKey(); SubjectKeyIdentifier subjectKeyID = CreateSubjectKeyID(pubKey); kName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, new DerSet(subjectKeyID))); } SafeBag kBag = null; if (!string.IsNullOrEmpty(encryptionPassword)) { kBag = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, kInfo.ToAsn1Object(), new DerSet(kName)); } else { kBag = new SafeBag(PkcsObjectIdentifiers.KeyBag, 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 = store.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); } var certs = store.Aliases.OfType <string>().Select(store.GetCertificate); foreach (var cert in certs) { //X509CertificateEntry cert = (X509CertificateEntry)certs[certId]; //if (keys[certId] != null) // continue; 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; } 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)))); fName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(CreateSubjectKeyID(cert.Certificate.GetPublicKey()).GetKeyIdentifier())))); } SafeBag sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName)); certSeq.Add(sBag); doneCerts.Add(cert.Certificate); } var chainCerts = store.Aliases.OfType <string>().Select(store.GetCertificateChain).Aggregate <IEnumerable <X509CertificateEntry>, IEnumerable <X509CertificateEntry> >(new List <X509CertificateEntry>(), (list, entries) => list.Union(entries)); foreach (var cert in chainCerts) { //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(); Func <bool, AlgorithmIdentifier, char[], bool, byte[], byte[]> CryptPbeData = (forEncryption_, algId_, password_, wrongPkcs12Zero_, data_) => { var method = T.GetMethod("CryptPbeData", BindingFlags.NonPublic | BindingFlags.Static); return((byte[])method.Invoke(store, new object[] { forEncryption_, algId_, password_, wrongPkcs12Zero_, data_ })); }; ContentInfo[] info = null; if (null != encryptionPassword) { byte[] certBytes = CryptPbeData(true, cAlgId, encryptionPassword.ToArray(), false, derEncodedBytes); var cInfo = new EncryptedData(PkcsObjectIdentifiers.Data, cAlgId, new BerOctetString(certBytes)); info = new ContentInfo[] { new ContentInfo(PkcsObjectIdentifiers.Data, keyString), new ContentInfo(PkcsObjectIdentifiers.EncryptedData, cInfo.ToAsn1Object()) }; } else { var cInfo = new BerOctetString(derEncodedBytes); info = new ContentInfo[] { new ContentInfo(PkcsObjectIdentifiers.Data, keyString), new ContentInfo(PkcsObjectIdentifiers.Data, cInfo.ToAsn1Object()) }; } byte[] data = new AuthenticatedSafe(info).GetEncoded(Asn1Encodable.Der); ContentInfo mainInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(data)); // // create the mac // byte[] mSalt = new byte[saltSize]; random.NextBytes(mSalt); Func <DerObjectIdentifier, byte[], int, char[], bool, byte[], byte[]> CalculatePbeMac = (oid_, salt_, itCount_, password_, wrongPkcs12Zero_, data_) => { var method = T.GetMethod("CalculatePbeMac", BindingFlags.NonPublic | BindingFlags.Static); return((byte[])method.Invoke(store, new object[] { oid_, salt_, itCount_, password_, wrongPkcs12Zero_, data_ })); }; MacData mData = null; if (null != integrityPassword) { //byte[] mac = CalculatePbeMac(OiwObjectIdentifiers.IdSha1, mSalt, minIterations, integrityPassword.ToArray(), false, data); byte[] mac = CalculatePbeMac(PbeUtilities.GetObjectIdentifier("PBEwithHmacSHA-256"), mSalt, minIterations, integrityPassword.ToArray(), false, data); //AlgorithmIdentifier algId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance); AlgorithmIdentifier algId = new AlgorithmIdentifier(PbeUtilities.GetObjectIdentifier("PBEwithHmacSHA-256"), DerNull.Instance); DigestInfo dInfo = new DigestInfo(algId, mac); mData = new MacData(dInfo, mSalt, minIterations); } // // output the Pfx // Pfx pfx = new Pfx(mainInfo, mData); DerOutputStream derOut = new DerOutputStream(stream); derOut.WriteObject(pfx); }
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); }