Pkcs12Store
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Misc;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Operators.Utilities;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Extension;
using System;
using System.Collections.Generic;
using System.IO;
namespace Org.BouncyCastle.Pkcs
{
public class Pkcs12Store
{
private struct CertID : IEquatable<CertID>
{
private readonly byte[] m_id;
internal byte[] ID => m_id;
internal CertID(X509CertificateEntry certEntry)
{
this = new CertID(certEntry.Certificate);
}
internal CertID(X509Certificate cert)
{
this = new CertID(CreateLocalKeyID(cert));
}
internal CertID(Asn1OctetString id)
{
m_id = id.GetOctets();
}
public bool Equals(CertID other)
{
return Arrays.AreEqual(m_id, other.m_id);
}
public override bool Equals(object obj)
{
if (obj is CertID) {
CertID other = (CertID)obj;
return Equals(other);
}
return false;
}
public override int GetHashCode()
{
return Arrays.GetHashCode(m_id);
}
}
public const string IgnoreUselessPasswordProperty = "Org.BouncyCastle.Pkcs12.IgnoreUselessPassword";
private readonly Dictionary<string, AsymmetricKeyEntry> m_keys = new Dictionary<string, AsymmetricKeyEntry>(StringComparer.OrdinalIgnoreCase);
private readonly List<string> m_keysOrder = new List<string>();
private readonly Dictionary<string, string> m_localIDs = new Dictionary<string, string>();
private readonly Dictionary<string, X509CertificateEntry> m_certs = new Dictionary<string, X509CertificateEntry>(StringComparer.OrdinalIgnoreCase);
private readonly List<string> m_certsOrder = new List<string>();
private readonly Dictionary<CertID, X509CertificateEntry> m_chainCerts = new Dictionary<CertID, X509CertificateEntry>();
private readonly List<CertID> m_chainCertsOrder = new List<CertID>();
private readonly Dictionary<string, X509CertificateEntry> m_keyCerts = new Dictionary<string, X509CertificateEntry>(StringComparer.OrdinalIgnoreCase);
private readonly DerObjectIdentifier certAlgorithm;
private readonly DerObjectIdentifier certPrfAlgorithm;
private readonly DerObjectIdentifier keyAlgorithm;
private readonly DerObjectIdentifier keyPrfAlgorithm;
private readonly bool useDerEncoding;
private readonly bool reverseCertificates;
private readonly bool overwriteFriendlyName;
private readonly bool enableOracleTrustedKeyUsage;
private AsymmetricKeyEntry unmarkedKeyEntry;
private const int MinIterations = 1024;
private const int SaltSize = 20;
public IEnumerable<string> Aliases {
get {
HashSet<string> hashSet = new HashSet<string>(m_certs.Keys);
hashSet.UnionWith(m_keys.Keys);
return CollectionUtilities.Proxy(hashSet);
}
}
public int Count {
get {
int num = m_certs.Count;
foreach (string key in m_keys.Keys) {
if (!m_certs.ContainsKey(key))
num++;
}
return num;
}
}
internal Pkcs12Store(DerObjectIdentifier certAlgorithm, DerObjectIdentifier certPrfAlgorithm, DerObjectIdentifier keyAlgorithm, DerObjectIdentifier keyPrfAlgorithm, bool useDerEncoding, bool reverseCertificates, bool overwriteFriendlyName, bool enableOracleTrustedKeyUsage)
{
this.certAlgorithm = certAlgorithm;
this.certPrfAlgorithm = certPrfAlgorithm;
this.keyAlgorithm = keyAlgorithm;
this.keyPrfAlgorithm = keyPrfAlgorithm;
this.useDerEncoding = useDerEncoding;
this.reverseCertificates = reverseCertificates;
this.overwriteFriendlyName = overwriteFriendlyName;
this.enableOracleTrustedKeyUsage = enableOracleTrustedKeyUsage;
}
protected virtual void LoadKeyBag(PrivateKeyInfo privKeyInfo, Asn1Set bagAttributes)
{
AsymmetricKeyParameter key = PrivateKeyFactory.CreateKey(privKeyInfo);
Dictionary<DerObjectIdentifier, Asn1Encodable> dictionary = new Dictionary<DerObjectIdentifier, Asn1Encodable>();
AsymmetricKeyEntry v = new AsymmetricKeyEntry(key, dictionary);
string text = null;
Asn1OctetString asn1OctetString = null;
if (bagAttributes != null) {
foreach (Asn1Encodable bagAttribute in bagAttributes) {
Asn1Sequence instance = Asn1Sequence.GetInstance(bagAttribute);
DerObjectIdentifier instance2 = DerObjectIdentifier.GetInstance(instance[0]);
Asn1Set instance3 = Asn1Set.GetInstance(instance[1]);
if (instance3.Count >= 1) {
Asn1Encodable asn1Encodable = instance3[0];
if (dictionary.TryGetValue(instance2, out Asn1Encodable value)) {
if (!value.Equals(asn1Encodable))
throw new IOException("attempt to add existing attribute with different value");
} else
dictionary[instance2] = asn1Encodable;
if (PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Equals(instance2)) {
text = DerBmpString.GetInstance(asn1Encodable).GetString();
Map(m_keys, m_keysOrder, text, v);
} else if (PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Equals(instance2)) {
asn1OctetString = Asn1OctetString.GetInstance(asn1Encodable);
}
}
}
}
if (asn1OctetString != null) {
string text2 = Hex.ToHexString(asn1OctetString.GetOctets());
if (text == null)
Map(m_keys, m_keysOrder, text2, v);
else
m_localIDs[text] = text2;
} else
unmarkedKeyEntry = v;
}
protected virtual void LoadPkcs8ShroudedKeyBag(EncryptedPrivateKeyInfo encPrivKeyInfo, Asn1Set bagAttributes, char[] password, bool wrongPkcs12Zero)
{
PrivateKeyInfo privKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(password, wrongPkcs12Zero, encPrivKeyInfo);
LoadKeyBag(privKeyInfo, bagAttributes);
}
public void Load(Stream input, char[] password)
{
if (input == null)
throw new ArgumentNullException("input");
Pfx instance = Pfx.GetInstance(Asn1Object.FromStream(input));
ContentInfo authSafe = instance.AuthSafe;
bool wrongPkcs12Zero = false;
bool flag = false;
MacData macData = instance.MacData;
if (macData != null) {
flag = true;
if (password == null)
throw new ArgumentNullException("password", "no password supplied when one expected");
byte[] octets = Asn1OctetString.GetInstance(authSafe.Content).GetOctets();
if (!VerifyPbeMac(macData, password, false, octets)) {
if (password.Length != 0 || !VerifyPbeMac(macData, password, true, octets))
throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
wrongPkcs12Zero = true;
}
}
Clear(m_keys, m_keysOrder);
m_localIDs.Clear();
unmarkedKeyEntry = null;
List<SafeBag> list = new List<SafeBag>();
if (PkcsObjectIdentifiers.Data.Equals(authSafe.ContentType)) {
ContentInfo[] contentInfo = AuthenticatedSafe.GetInstance(Asn1OctetString.GetInstance(authSafe.Content).GetOctets()).GetContentInfo();
foreach (ContentInfo contentInfo2 in contentInfo) {
DerObjectIdentifier contentType = contentInfo2.ContentType;
byte[] array = null;
if (PkcsObjectIdentifiers.Data.Equals(contentType))
array = Asn1OctetString.GetInstance(contentInfo2.Content).GetOctets();
else if (PkcsObjectIdentifiers.EncryptedData.Equals(contentType)) {
flag = true;
EncryptedData instance2 = EncryptedData.GetInstance(contentInfo2.Content);
array = CryptPbeData(false, instance2.EncryptionAlgorithm, password, wrongPkcs12Zero, instance2.Content.GetOctets());
}
if (array != null) {
foreach (Asn1Encodable item in Asn1Sequence.GetInstance(array)) {
SafeBag instance3 = SafeBag.GetInstance(item);
DerObjectIdentifier bagID = instance3.BagID;
if (PkcsObjectIdentifiers.CertBag.Equals(bagID))
list.Add(instance3);
else if (PkcsObjectIdentifiers.KeyBag.Equals(bagID)) {
LoadKeyBag(PrivateKeyInfo.GetInstance(instance3.BagValueEncodable), instance3.BagAttributes);
} else if (PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag.Equals(bagID)) {
flag = true;
LoadPkcs8ShroudedKeyBag(EncryptedPrivateKeyInfo.GetInstance(instance3.BagValueEncodable), instance3.BagAttributes, password, wrongPkcs12Zero);
}
}
}
}
}
Clear(m_certs, m_certsOrder);
Clear(m_chainCerts, m_chainCertsOrder);
m_keyCerts.Clear();
foreach (SafeBag item2 in list) {
CertBag instance4 = CertBag.GetInstance(item2.BagValueEncodable);
if (!PkcsObjectIdentifiers.X509Certificate.Equals(instance4.CertID))
throw new Exception("Unsupported certificate type: " + instance4.CertID?.ToString());
X509Certificate cert = new X509Certificate(Asn1OctetString.GetInstance(instance4.CertValueEncodable).GetOctets());
Dictionary<DerObjectIdentifier, Asn1Encodable> dictionary = new Dictionary<DerObjectIdentifier, Asn1Encodable>();
Asn1OctetString asn1OctetString = null;
string text = null;
if (item2.BagAttributes != null) {
foreach (Asn1Encodable bagAttribute in item2.BagAttributes) {
Asn1Sequence instance5 = Asn1Sequence.GetInstance(bagAttribute);
DerObjectIdentifier instance6 = DerObjectIdentifier.GetInstance(instance5[0]);
Asn1Set instance7 = Asn1Set.GetInstance(instance5[1]);
if (instance7.Count >= 1) {
Asn1Encodable asn1Encodable = instance7[0];
if (dictionary.TryGetValue(instance6, out Asn1Encodable value)) {
if (PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Equals(instance6)) {
string key = Hex.ToHexString(Asn1OctetString.GetInstance(asn1Encodable).GetOctets());
if (!m_keys.ContainsKey(key) && !m_localIDs.ContainsKey(key))
continue;
}
if (!value.Equals(asn1Encodable))
throw new IOException("attempt to add existing attribute with different value");
} else
dictionary[instance6] = asn1Encodable;
if (PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Equals(instance6))
text = DerBmpString.GetInstance(asn1Encodable).GetString();
else if (PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Equals(instance6)) {
asn1OctetString = Asn1OctetString.GetInstance(asn1Encodable);
}
}
}
}
CertID k = new CertID(cert);
X509CertificateEntry x509CertificateEntry = new X509CertificateEntry(cert, dictionary);
Map(m_chainCerts, m_chainCertsOrder, k, x509CertificateEntry);
if (unmarkedKeyEntry != null) {
if (m_keyCerts.Count == 0) {
string text2 = Hex.ToHexString(k.ID);
m_keyCerts[text2] = x509CertificateEntry;
Map(m_keys, m_keysOrder, text2, unmarkedKeyEntry);
} else
Map(m_keys, m_keysOrder, "unmarked", unmarkedKeyEntry);
} else {
if (asn1OctetString != null) {
string key2 = Hex.ToHexString(asn1OctetString.GetOctets());
m_keyCerts[key2] = x509CertificateEntry;
}
if (text != null)
Map(m_certs, m_certsOrder, text, x509CertificateEntry);
}
}
if (!flag && password != null) {
string environmentVariable = Platform.GetEnvironmentVariable("Org.BouncyCastle.Pkcs12.IgnoreUselessPassword");
if (environmentVariable == null || !Platform.EqualsIgnoreCase("true", environmentVariable))
throw new IOException("password supplied for keystore that does not require one");
}
}
public AsymmetricKeyEntry GetKey(string alias)
{
if (alias == null)
throw new ArgumentNullException("alias");
return CollectionUtilities.GetValueOrNull(m_keys, alias);
}
public bool IsCertificateEntry(string alias)
{
if (alias == null)
throw new ArgumentNullException("alias");
if (m_certs.ContainsKey(alias))
return !m_keys.ContainsKey(alias);
return false;
}
public bool IsKeyEntry(string alias)
{
if (alias == null)
throw new ArgumentNullException("alias");
return m_keys.ContainsKey(alias);
}
public bool ContainsAlias(string alias)
{
if (alias == null)
throw new ArgumentNullException("alias");
if (!m_certs.ContainsKey(alias))
return m_keys.ContainsKey(alias);
return true;
}
public X509CertificateEntry GetCertificate(string alias)
{
if (alias == null)
throw new ArgumentNullException("alias");
if (m_certs.TryGetValue(alias, out X509CertificateEntry value))
return value;
string k = alias;
if (m_localIDs.TryGetValue(alias, out string value2))
k = value2;
return CollectionUtilities.GetValueOrNull(m_keyCerts, k);
}
public string GetCertificateAlias(X509Certificate cert)
{
if (cert == null)
throw new ArgumentNullException("cert");
Dictionary<string, X509CertificateEntry>.Enumerator enumerator = m_certs.GetEnumerator();
try {
while (enumerator.MoveNext()) {
KeyValuePair<string, X509CertificateEntry> current = enumerator.Current;
if (current.Value.Certificate.Equals(cert))
return current.Key;
}
} finally {
((IDisposable)enumerator).Dispose();
}
enumerator = m_keyCerts.GetEnumerator();
try {
while (enumerator.MoveNext()) {
KeyValuePair<string, X509CertificateEntry> current2 = enumerator.Current;
if (current2.Value.Certificate.Equals(cert))
return current2.Key;
}
} finally {
((IDisposable)enumerator).Dispose();
}
return null;
}
public X509CertificateEntry[] GetCertificateChain(string alias)
{
if (alias == null)
throw new ArgumentNullException("alias");
if (!IsKeyEntry(alias))
return null;
X509CertificateEntry x509CertificateEntry = GetCertificate(alias);
if (x509CertificateEntry == null)
return null;
List<X509CertificateEntry> list = new List<X509CertificateEntry>();
while (x509CertificateEntry != null) {
X509Certificate certificate = x509CertificateEntry.Certificate;
X509CertificateEntry x509CertificateEntry2 = null;
AuthorityKeyIdentifier authorityKeyIdentifier = X509ExtensionUtilities.GetAuthorityKeyIdentifier(certificate);
if (authorityKeyIdentifier != null) {
Asn1OctetString keyIdentifier = authorityKeyIdentifier.KeyIdentifier;
if (keyIdentifier != null)
x509CertificateEntry2 = CollectionUtilities.GetValueOrNull(m_chainCerts, new CertID(keyIdentifier));
}
if (x509CertificateEntry2 == null) {
X509Name issuerDN = certificate.IssuerDN;
X509Name subjectDN = certificate.SubjectDN;
if (!issuerDN.Equivalent(subjectDN)) {
foreach (KeyValuePair<CertID, X509CertificateEntry> chainCert in m_chainCerts) {
X509Certificate certificate2 = chainCert.Value.Certificate;
if (certificate2.SubjectDN.Equivalent(issuerDN)) {
try {
certificate.Verify(certificate2.GetPublicKey());
x509CertificateEntry2 = chainCert.Value;
} catch (InvalidKeyException) {
continue;
}
break;
}
}
}
}
list.Add(x509CertificateEntry);
x509CertificateEntry = ((x509CertificateEntry2 == x509CertificateEntry) ? null : x509CertificateEntry2);
}
return list.ToArray();
}
public void SetCertificateEntry(string alias, X509CertificateEntry certEntry)
{
if (alias == null)
throw new ArgumentNullException("alias");
if (certEntry == null)
throw new ArgumentNullException("certEntry");
if (m_keys.ContainsKey(alias))
throw new ArgumentException("There is a key entry with the name " + alias + ".");
Map(m_certs, m_certsOrder, alias, certEntry);
Map(m_chainCerts, m_chainCertsOrder, new CertID(certEntry), certEntry);
}
public void SetFriendlyName(string alias, string newFriendlyName)
{
if (alias == null)
throw new ArgumentNullException("alias");
if (newFriendlyName == null)
throw new ArgumentNullException("newFriendlyName");
if (!alias.Equals(newFriendlyName) && !overwriteFriendlyName) {
if (CollectionUtilities.Remove(m_certs, alias, out X509CertificateEntry v)) {
DeleteCertsEntry(newFriendlyName);
v.SetFriendlyName(newFriendlyName);
m_certs.Add(newFriendlyName, v);
ReplaceOrdering(m_certs.Comparer, m_certsOrder, alias, newFriendlyName);
}
if (CollectionUtilities.Remove(m_keys, alias, out AsymmetricKeyEntry v2)) {
DeleteKeysEntry(newFriendlyName);
v2.SetFriendlyName(newFriendlyName);
m_keys.Add(newFriendlyName, v2);
ReplaceOrdering(m_keys.Comparer, m_keysOrder, alias, newFriendlyName);
X509CertificateEntry v4;
if (CollectionUtilities.Remove(m_localIDs, alias, out string v3))
m_localIDs.Add(newFriendlyName, v3);
else if (CollectionUtilities.Remove(m_keyCerts, alias, out v4)) {
v4.SetFriendlyName(newFriendlyName);
m_keyCerts.Add(newFriendlyName, v4);
}
}
}
}
public void SetKeyEntry(string alias, AsymmetricKeyEntry keyEntry, X509CertificateEntry[] chain)
{
if (alias == null)
throw new ArgumentNullException("alias");
if (keyEntry == null)
throw new ArgumentNullException("keyEntry");
bool flag = !Arrays.IsNullOrEmpty(chain);
if (keyEntry.Key.IsPrivate && !flag)
throw new ArgumentException("No certificate chain for private key", "chain");
if (m_keys.ContainsKey(alias))
DeleteEntry(alias);
Map(m_keys, m_keysOrder, alias, keyEntry);
if (flag) {
Map(m_certs, m_certsOrder, alias, chain[0]);
foreach (X509CertificateEntry x509CertificateEntry in chain) {
Map(m_chainCerts, m_chainCertsOrder, new CertID(x509CertificateEntry), x509CertificateEntry);
}
}
}
public void DeleteEntry(string alias)
{
if (alias == null)
throw new ArgumentNullException("alias");
DeleteCertsEntry(alias);
DeleteKeysEntry(alias);
}
private void DeleteCertsEntry(string alias)
{
if (Remove(m_certs, m_certsOrder, alias, out X509CertificateEntry v))
Remove(m_chainCerts, m_chainCertsOrder, new CertID(v));
}
private void DeleteKeysEntry(string alias)
{
if (Remove(m_keys, m_keysOrder, alias)) {
string k = alias;
if (CollectionUtilities.Remove(m_localIDs, alias, out string v))
k = v;
if (CollectionUtilities.Remove(m_keyCerts, k, out X509CertificateEntry v2))
Remove(m_chainCerts, m_chainCertsOrder, new CertID(v2));
}
}
public bool IsEntryOfType(string alias, Type entryType)
{
if (entryType == typeof(X509CertificateEntry))
return IsCertificateEntry(alias);
if (entryType == typeof(AsymmetricKeyEntry)) {
if (IsKeyEntry(alias))
return GetCertificate(alias) != null;
return false;
}
return false;
}
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(m_keys.Count);
for (uint num = (uint)(reverseCertificates ? (m_keysOrder.Count - 1) : 0); num < m_keysOrder.Count; num = (reverseCertificates ? (num - 1) : (num + 1))) {
string text = m_keysOrder[(int)num];
AsymmetricKeyEntry asymmetricKeyEntry = m_keys[text];
byte[] nextBytes = SecureRandom.GetNextBytes(random, 20);
DerObjectIdentifier bagID;
Asn1Encodable bagValue;
if (password == null || keyAlgorithm == null) {
bagID = PkcsObjectIdentifiers.KeyBag;
bagValue = PrivateKeyInfoFactory.CreatePrivateKeyInfo(asymmetricKeyEntry.Key);
} else {
bagID = PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag;
bagValue = ((keyPrfAlgorithm == null) ? EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(keyAlgorithm, password, nextBytes, 1024, asymmetricKeyEntry.Key) : EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(keyAlgorithm, keyPrfAlgorithm, password, nextBytes, 1024, random, asymmetricKeyEntry.Key));
}
Asn1EncodableVector asn1EncodableVector2 = new Asn1EncodableVector();
foreach (DerObjectIdentifier bagAttributeKey in asymmetricKeyEntry.BagAttributeKeys) {
if (!PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Equals(bagAttributeKey))
asn1EncodableVector2.Add(new DerSequence(bagAttributeKey, new DerSet(asymmetricKeyEntry[bagAttributeKey])));
}
asn1EncodableVector2.Add(CreateEntryFriendlyName(text, asymmetricKeyEntry));
if (asymmetricKeyEntry[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
AddLocalKeyID(asn1EncodableVector2, GetCertificate(text));
asn1EncodableVector.Add(new SafeBag(bagID, bagValue, DerSet.FromVector(asn1EncodableVector2)));
}
byte[] derEncoded = new DerSequence(asn1EncodableVector).GetDerEncoded();
ContentInfo contentInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(derEncoded));
Asn1EncodableVector asn1EncodableVector3 = new Asn1EncodableVector(m_keys.Count);
HashSet<X509Certificate> hashSet = new HashSet<X509Certificate>();
for (uint num2 = (uint)(reverseCertificates ? (m_keysOrder.Count - 1) : 0); num2 < m_keysOrder.Count; num2 = (reverseCertificates ? (num2 - 1) : (num2 + 1))) {
string alias = m_keysOrder[(int)num2];
X509CertificateEntry certificate = GetCertificate(alias);
CertBag bagValue2 = CreateCertBag(certificate.Certificate);
Asn1EncodableVector asn1EncodableVector4 = new Asn1EncodableVector();
foreach (DerObjectIdentifier bagAttributeKey2 in certificate.BagAttributeKeys) {
if (!PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Equals(bagAttributeKey2))
asn1EncodableVector4.Add(new DerSequence(bagAttributeKey2, new DerSet(certificate[bagAttributeKey2])));
}
asn1EncodableVector4.Add(CreateEntryFriendlyName(alias, certificate));
if (certificate[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
AddLocalKeyID(asn1EncodableVector4, certificate);
asn1EncodableVector3.Add(new SafeBag(PkcsObjectIdentifiers.CertBag, bagValue2, DerSet.FromVector(asn1EncodableVector4)));
hashSet.Add(certificate.Certificate);
}
for (uint num3 = (uint)(reverseCertificates ? (m_certsOrder.Count - 1) : 0); num3 < m_certsOrder.Count; num3 = (reverseCertificates ? (num3 - 1) : (num3 + 1))) {
string text2 = m_certsOrder[(int)num3];
X509CertificateEntry x509CertificateEntry = m_certs[text2];
if (!m_keys.ContainsKey(text2)) {
CertBag bagValue3 = CreateCertBag(x509CertificateEntry.Certificate);
Asn1EncodableVector asn1EncodableVector5 = new Asn1EncodableVector();
foreach (DerObjectIdentifier bagAttributeKey3 in x509CertificateEntry.BagAttributeKeys) {
if (!PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Equals(bagAttributeKey3) && !PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Equals(bagAttributeKey3) && !MiscObjectIdentifiers.id_oracle_pkcs12_trusted_key_usage.Equals(bagAttributeKey3))
asn1EncodableVector5.Add(new DerSequence(bagAttributeKey3, new DerSet(x509CertificateEntry[bagAttributeKey3])));
}
asn1EncodableVector5.Add(CreateEntryFriendlyName(text2, x509CertificateEntry));
if (enableOracleTrustedKeyUsage) {
Asn1Object extensionParsedValue = x509CertificateEntry.Certificate.GetExtensionParsedValue(X509Extensions.ExtendedKeyUsage);
DerSet element;
if (extensionParsedValue != null) {
Asn1Encodable[] allUsagesArray = ExtendedKeyUsage.GetInstance(extensionParsedValue).GetAllUsagesArray();
element = new DerSet(allUsagesArray);
} else
element = new DerSet(KeyPurposeID.AnyExtendedKeyUsage);
asn1EncodableVector5.Add(new DerSequence(MiscObjectIdentifiers.id_oracle_pkcs12_trusted_key_usage, element));
}
asn1EncodableVector3.Add(new SafeBag(PkcsObjectIdentifiers.CertBag, bagValue3, DerSet.FromVector(asn1EncodableVector5)));
hashSet.Add(x509CertificateEntry.Certificate);
}
}
for (uint num4 = (uint)(reverseCertificates ? (m_chainCertsOrder.Count - 1) : 0); num4 < m_chainCertsOrder.Count; num4 = (reverseCertificates ? (num4 - 1) : (num4 + 1))) {
CertID key = m_chainCertsOrder[(int)num4];
X509CertificateEntry x509CertificateEntry2 = m_chainCerts[key];
X509Certificate certificate2 = x509CertificateEntry2.Certificate;
if (!hashSet.Contains(certificate2)) {
CertBag bagValue4 = CreateCertBag(certificate2);
Asn1EncodableVector asn1EncodableVector6 = new Asn1EncodableVector();
foreach (DerObjectIdentifier bagAttributeKey4 in x509CertificateEntry2.BagAttributeKeys) {
if (!PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Equals(bagAttributeKey4))
asn1EncodableVector6.Add(new DerSequence(bagAttributeKey4, new DerSet(x509CertificateEntry2[bagAttributeKey4])));
}
asn1EncodableVector3.Add(new SafeBag(PkcsObjectIdentifiers.CertBag, bagValue4, DerSet.FromVector(asn1EncodableVector6)));
}
}
byte[] derEncoded2 = new DerSequence(asn1EncodableVector3).GetDerEncoded();
ContentInfo contentInfo2;
if (password == null || certAlgorithm == null)
contentInfo2 = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(derEncoded2));
else {
byte[] nextBytes2 = SecureRandom.GetNextBytes(random, 20);
int num5 = 1024;
AlgorithmIdentifier algorithmIdentifier;
if (certPrfAlgorithm != null) {
Asn1Encodable parameters = PbeUtilities.GenerateAlgorithmParameters(certAlgorithm, certPrfAlgorithm, nextBytes2, num5, random);
algorithmIdentifier = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPbeS2, parameters);
} else {
Pkcs12PbeParams parameters2 = new Pkcs12PbeParams(nextBytes2, num5);
algorithmIdentifier = new AlgorithmIdentifier(certAlgorithm, parameters2);
}
byte[] contents = CryptPbeData(true, algorithmIdentifier, password, false, derEncoded2);
contentInfo2 = new ContentInfo(PkcsObjectIdentifiers.EncryptedData, new EncryptedData(PkcsObjectIdentifiers.Data, algorithmIdentifier, new BerOctetString(contents)));
}
byte[] encoded = new AuthenticatedSafe(new ContentInfo[2] {
contentInfo,
contentInfo2
}).GetEncoded(useDerEncoding ? "DER" : "BER");
ContentInfo contentInfo3 = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(encoded));
MacData macData = null;
if (password != null) {
AlgorithmIdentifier algorithmIdentifier2 = DefaultDigestAlgorithmFinder.Instance.Find(OiwObjectIdentifiers.IdSha1);
byte[] nextBytes3 = SecureRandom.GetNextBytes(random, 20);
int num6 = 1024;
byte[] contents2 = CalculatePbeMac(algorithmIdentifier2, nextBytes3, num6, password, false, encoded);
macData = new MacData(new DigestInfo(algorithmIdentifier2, new DerOctetString(contents2)), nextBytes3, num6);
}
new Pfx(contentInfo3, macData).EncodeTo(stream, useDerEncoding ? "DER" : "BER");
}
private DerSequence CreateEntryFriendlyName(string alias, Pkcs12Entry entry)
{
DerSet element = DerSet.Empty;
Asn1Encodable attribute;
if (overwriteFriendlyName)
element = new DerSet(new DerBmpString(alias));
else if (entry.TryGetAttribute(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, out attribute)) {
element = new DerSet(attribute);
}
return new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, element);
}
internal static byte[] CalculatePbeMac(AlgorithmIdentifier macDigestAlgorithm, byte[] salt, int iterations, char[] password, bool wrongPkcs12Zero, byte[] data)
{
DerObjectIdentifier algorithm = macDigestAlgorithm.Algorithm;
Asn1Encodable pbeParameters = PbeUtilities.GenerateAlgorithmParameters(algorithm, salt, iterations);
ICipherParameters parameters = PbeUtilities.GenerateCipherParameters(algorithm, password, wrongPkcs12Zero, pbeParameters);
IMac obj = (IMac)PbeUtilities.CreateEngine(algorithm);
obj.Init(parameters);
return MacUtilities.DoFinal(obj, data);
}
internal static bool VerifyPbeMac(MacData macData, char[] password, bool wrongPkcs12Zero, byte[] data)
{
DigestInfo mac = macData.Mac;
return Arrays.FixedTimeEquals(CalculatePbeMac(mac.DigestAlgorithm, macData.MacSalt.GetOctets(), macData.Iterations.IntValueExact, password, wrongPkcs12Zero, data), mac.Digest.GetOctets());
}
private static void AddLocalKeyID(Asn1EncodableVector v, X509CertificateEntry certEntry)
{
AddLocalKeyID(v, certEntry.Certificate);
}
private static void AddLocalKeyID(Asn1EncodableVector v, X509Certificate c)
{
v.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, new DerSet(CreateLocalKeyID(c))));
}
private static CertBag CreateCertBag(X509Certificate c)
{
return new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(c.GetEncoded()));
}
private static Asn1OctetString CreateLocalKeyID(X509Certificate certificate)
{
return X509ExtensionUtilities.CalculateKeyIdentifier(certificate);
}
private static byte[] CryptPbeData(bool forEncryption, AlgorithmIdentifier algID, char[] password, bool wrongPkcs12Zero, byte[] data)
{
IBufferedCipher obj = PbeUtilities.CreateEngine(algID) as IBufferedCipher;
if (obj == null)
throw new Exception("Unknown encryption algorithm: " + algID.Algorithm?.ToString());
Asn1Encodable instance;
if (PkcsObjectIdentifiers.IdPbeS2.Equals(algID.Algorithm)) {
wrongPkcs12Zero = false;
instance = PbeS2Parameters.GetInstance(algID.Parameters);
} else
instance = Pkcs12PbeParams.GetInstance(algID.Parameters);
ICipherParameters parameters = PbeUtilities.GenerateCipherParameters(algID.Algorithm, password, wrongPkcs12Zero, instance);
obj.Init(forEncryption, parameters);
return obj.DoFinal(data);
}
private static void Clear<K, V>(Dictionary<K, V> d, List<K> o)
{
d.Clear();
o.Clear();
}
private static void Map<K, V>(Dictionary<K, V> d, List<K> o, K k, V v)
{
if (d.ContainsKey(k))
RemoveOrdering(d.Comparer, o, k);
o.Add(k);
d[k] = v;
}
private static bool Remove<K, V>(Dictionary<K, V> d, List<K> o, K k)
{
bool num = d.Remove(k);
if (num)
RemoveOrdering(d.Comparer, o, k);
return num;
}
private static bool Remove<K, V>(Dictionary<K, V> d, List<K> o, K k, out V v)
{
bool num = CollectionUtilities.Remove(d, k, out v);
if (num)
RemoveOrdering(d.Comparer, o, k);
return num;
}
private static void RemoveOrdering<K>(IEqualityComparer<K> c, List<K> o, K k)
{
int num = o.FindIndex((Predicate<K>)((K e) => c.Equals(k, e)));
if (num >= 0)
o.RemoveAt(num);
}
private static void ReplaceOrdering<K>(IEqualityComparer<K> c, List<K> o, K oldKey, K newKey)
{
int num = o.FindIndex((Predicate<K>)((K e) => c.Equals(oldKey, e)));
if (num >= 0)
o[num] = newKey;
}
}
}