init commit
This commit is contained in:
@@ -0,0 +1,824 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Oiw;
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.Collections;
|
||||
using Org.BouncyCastle.Utilities.Encoders;
|
||||
using Org.BouncyCastle.X509;
|
||||
|
||||
namespace Org.BouncyCastle.Pkcs;
|
||||
|
||||
public class Pkcs12Store
|
||||
{
|
||||
internal class CertId
|
||||
{
|
||||
private readonly byte[] id;
|
||||
|
||||
internal byte[] Id => id;
|
||||
|
||||
internal CertId(AsymmetricKeyParameter pubKey)
|
||||
{
|
||||
id = CreateSubjectKeyID(pubKey).GetKeyIdentifier();
|
||||
}
|
||||
|
||||
internal CertId(byte[] id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Arrays.GetHashCode(id);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == this)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!(obj is CertId certId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Arrays.AreEqual(id, certId.id);
|
||||
}
|
||||
}
|
||||
|
||||
private class IgnoresCaseHashtable : IEnumerable
|
||||
{
|
||||
private readonly IDictionary orig = Platform.CreateHashtable();
|
||||
|
||||
private readonly IDictionary keys = Platform.CreateHashtable();
|
||||
|
||||
public ICollection Keys => orig.Keys;
|
||||
|
||||
public object this[string alias]
|
||||
{
|
||||
get
|
||||
{
|
||||
string key = Platform.ToUpperInvariant(alias);
|
||||
string text = (string)keys[key];
|
||||
if (text == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return orig[text];
|
||||
}
|
||||
set
|
||||
{
|
||||
string key = Platform.ToUpperInvariant(alias);
|
||||
string text = (string)keys[key];
|
||||
if (text != null)
|
||||
{
|
||||
orig.Remove(text);
|
||||
}
|
||||
keys[key] = alias;
|
||||
orig[alias] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection Values => orig.Values;
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
orig.Clear();
|
||||
keys.Clear();
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
return orig.GetEnumerator();
|
||||
}
|
||||
|
||||
public object Remove(string alias)
|
||||
{
|
||||
string key = Platform.ToUpperInvariant(alias);
|
||||
string text = (string)keys[key];
|
||||
if (text == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
keys.Remove(key);
|
||||
object result = orig[text];
|
||||
orig.Remove(text);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private const int MinIterations = 1024;
|
||||
|
||||
private const int SaltSize = 20;
|
||||
|
||||
private readonly IgnoresCaseHashtable keys = new IgnoresCaseHashtable();
|
||||
|
||||
private readonly IDictionary localIds = Platform.CreateHashtable();
|
||||
|
||||
private readonly IgnoresCaseHashtable certs = new IgnoresCaseHashtable();
|
||||
|
||||
private readonly IDictionary chainCerts = Platform.CreateHashtable();
|
||||
|
||||
private readonly IDictionary keyCerts = Platform.CreateHashtable();
|
||||
|
||||
private readonly DerObjectIdentifier keyAlgorithm;
|
||||
|
||||
private readonly DerObjectIdentifier certAlgorithm;
|
||||
|
||||
private readonly bool useDerEncoding;
|
||||
|
||||
private AsymmetricKeyEntry unmarkedKeyEntry = null;
|
||||
|
||||
public IEnumerable Aliases => new EnumerableProxy(GetAliasesTable().Keys);
|
||||
|
||||
public int Count => GetAliasesTable().Count;
|
||||
|
||||
private static SubjectKeyIdentifier CreateSubjectKeyID(AsymmetricKeyParameter pubKey)
|
||||
{
|
||||
return new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey));
|
||||
}
|
||||
|
||||
internal Pkcs12Store(DerObjectIdentifier keyAlgorithm, DerObjectIdentifier certAlgorithm, bool useDerEncoding)
|
||||
{
|
||||
this.keyAlgorithm = keyAlgorithm;
|
||||
this.certAlgorithm = certAlgorithm;
|
||||
this.useDerEncoding = useDerEncoding;
|
||||
}
|
||||
|
||||
public Pkcs12Store()
|
||||
: this(PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc, PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc, useDerEncoding: false)
|
||||
{
|
||||
}
|
||||
|
||||
public Pkcs12Store(Stream input, char[] password)
|
||||
: this()
|
||||
{
|
||||
Load(input, password);
|
||||
}
|
||||
|
||||
protected virtual void LoadKeyBag(PrivateKeyInfo privKeyInfo, Asn1Set bagAttributes)
|
||||
{
|
||||
AsymmetricKeyParameter key = PrivateKeyFactory.CreateKey(privKeyInfo);
|
||||
IDictionary dictionary = Platform.CreateHashtable();
|
||||
AsymmetricKeyEntry value = new AsymmetricKeyEntry(key, dictionary);
|
||||
string text = null;
|
||||
Asn1OctetString asn1OctetString = null;
|
||||
if (bagAttributes != null)
|
||||
{
|
||||
foreach (Asn1Sequence bagAttribute in bagAttributes)
|
||||
{
|
||||
DerObjectIdentifier instance = DerObjectIdentifier.GetInstance(bagAttribute[0]);
|
||||
Asn1Set instance2 = Asn1Set.GetInstance(bagAttribute[1]);
|
||||
Asn1Encodable asn1Encodable = null;
|
||||
if (instance2.Count <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
asn1Encodable = instance2[0];
|
||||
if (dictionary.Contains(instance.Id))
|
||||
{
|
||||
if (!dictionary[instance.Id].Equals(asn1Encodable))
|
||||
{
|
||||
throw new IOException("attempt to add existing attribute with different value");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(instance.Id, asn1Encodable);
|
||||
}
|
||||
if (instance.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
|
||||
{
|
||||
text = ((DerBmpString)asn1Encodable).GetString();
|
||||
keys[text] = value;
|
||||
}
|
||||
else if (instance.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
|
||||
{
|
||||
asn1OctetString = (Asn1OctetString)asn1Encodable;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (asn1OctetString != null)
|
||||
{
|
||||
string text2 = Hex.ToHexString(asn1OctetString.GetOctets());
|
||||
if (text == null)
|
||||
{
|
||||
keys[text2] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
localIds[text] = text2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unmarkedKeyEntry = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void LoadPkcs8ShroudedKeyBag(EncryptedPrivateKeyInfo encPrivKeyInfo, Asn1Set bagAttributes, char[] password, bool wrongPkcs12Zero)
|
||||
{
|
||||
if (password != null)
|
||||
{
|
||||
PrivateKeyInfo privKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(password, wrongPkcs12Zero, encPrivKeyInfo);
|
||||
LoadKeyBag(privKeyInfo, bagAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
public void Load(Stream input, char[] password)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
throw new ArgumentNullException("input");
|
||||
}
|
||||
Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromStream(input);
|
||||
Pfx pfx = new Pfx(seq);
|
||||
ContentInfo authSafe = pfx.AuthSafe;
|
||||
bool wrongPkcs12Zero = false;
|
||||
if (password != null && pfx.MacData != null)
|
||||
{
|
||||
MacData macData = pfx.MacData;
|
||||
DigestInfo mac = macData.Mac;
|
||||
AlgorithmIdentifier algorithmID = mac.AlgorithmID;
|
||||
byte[] salt = macData.GetSalt();
|
||||
int intValue = macData.IterationCount.IntValue;
|
||||
byte[] octets = ((Asn1OctetString)authSafe.Content).GetOctets();
|
||||
byte[] a = CalculatePbeMac(algorithmID.Algorithm, salt, intValue, password, wrongPkcs12Zero: false, octets);
|
||||
byte[] digest = mac.GetDigest();
|
||||
if (!Arrays.ConstantTimeAreEqual(a, digest))
|
||||
{
|
||||
if (password.Length > 0)
|
||||
{
|
||||
throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
|
||||
}
|
||||
a = CalculatePbeMac(algorithmID.Algorithm, salt, intValue, password, wrongPkcs12Zero: true, octets);
|
||||
if (!Arrays.ConstantTimeAreEqual(a, digest))
|
||||
{
|
||||
throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
|
||||
}
|
||||
wrongPkcs12Zero = true;
|
||||
}
|
||||
}
|
||||
keys.Clear();
|
||||
localIds.Clear();
|
||||
unmarkedKeyEntry = null;
|
||||
IList list = Platform.CreateArrayList();
|
||||
if (authSafe.ContentType.Equals(PkcsObjectIdentifiers.Data))
|
||||
{
|
||||
byte[] octets2 = ((Asn1OctetString)authSafe.Content).GetOctets();
|
||||
AuthenticatedSafe authenticatedSafe = new AuthenticatedSafe((Asn1Sequence)Asn1Object.FromByteArray(octets2));
|
||||
ContentInfo[] contentInfo = authenticatedSafe.GetContentInfo();
|
||||
ContentInfo[] array = contentInfo;
|
||||
foreach (ContentInfo contentInfo2 in array)
|
||||
{
|
||||
DerObjectIdentifier contentType = contentInfo2.ContentType;
|
||||
byte[] array2 = null;
|
||||
if (contentType.Equals(PkcsObjectIdentifiers.Data))
|
||||
{
|
||||
array2 = ((Asn1OctetString)contentInfo2.Content).GetOctets();
|
||||
}
|
||||
else if (contentType.Equals(PkcsObjectIdentifiers.EncryptedData) && password != null)
|
||||
{
|
||||
EncryptedData instance = EncryptedData.GetInstance(contentInfo2.Content);
|
||||
array2 = CryptPbeData(forEncryption: false, instance.EncryptionAlgorithm, password, wrongPkcs12Zero, instance.Content.GetOctets());
|
||||
}
|
||||
if (array2 == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Asn1Sequence asn1Sequence = (Asn1Sequence)Asn1Object.FromByteArray(array2);
|
||||
foreach (Asn1Sequence item in asn1Sequence)
|
||||
{
|
||||
SafeBag safeBag = new SafeBag(item);
|
||||
if (safeBag.BagID.Equals(PkcsObjectIdentifiers.CertBag))
|
||||
{
|
||||
list.Add(safeBag);
|
||||
}
|
||||
else if (safeBag.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
|
||||
{
|
||||
LoadPkcs8ShroudedKeyBag(EncryptedPrivateKeyInfo.GetInstance(safeBag.BagValue), safeBag.BagAttributes, password, wrongPkcs12Zero);
|
||||
}
|
||||
else if (safeBag.BagID.Equals(PkcsObjectIdentifiers.KeyBag))
|
||||
{
|
||||
LoadKeyBag(PrivateKeyInfo.GetInstance(safeBag.BagValue), safeBag.BagAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
certs.Clear();
|
||||
chainCerts.Clear();
|
||||
keyCerts.Clear();
|
||||
foreach (SafeBag item2 in list)
|
||||
{
|
||||
CertBag certBag = new CertBag((Asn1Sequence)item2.BagValue);
|
||||
byte[] octets3 = ((Asn1OctetString)certBag.CertValue).GetOctets();
|
||||
X509Certificate x509Certificate = new X509CertificateParser().ReadCertificate(octets3);
|
||||
IDictionary dictionary = Platform.CreateHashtable();
|
||||
Asn1OctetString asn1OctetString = null;
|
||||
string text = null;
|
||||
if (item2.BagAttributes != null)
|
||||
{
|
||||
foreach (Asn1Sequence bagAttribute in item2.BagAttributes)
|
||||
{
|
||||
DerObjectIdentifier instance2 = DerObjectIdentifier.GetInstance(bagAttribute[0]);
|
||||
Asn1Set instance3 = Asn1Set.GetInstance(bagAttribute[1]);
|
||||
if (instance3.Count <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Asn1Encodable asn1Encodable = instance3[0];
|
||||
if (dictionary.Contains(instance2.Id))
|
||||
{
|
||||
if (!dictionary[instance2.Id].Equals(asn1Encodable))
|
||||
{
|
||||
throw new IOException("attempt to add existing attribute with different value");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dictionary.Add(instance2.Id, asn1Encodable);
|
||||
}
|
||||
if (instance2.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
|
||||
{
|
||||
text = ((DerBmpString)asn1Encodable).GetString();
|
||||
}
|
||||
else if (instance2.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
|
||||
{
|
||||
asn1OctetString = (Asn1OctetString)asn1Encodable;
|
||||
}
|
||||
}
|
||||
}
|
||||
CertId certId = new CertId(x509Certificate.GetPublicKey());
|
||||
X509CertificateEntry value = new X509CertificateEntry(x509Certificate, dictionary);
|
||||
chainCerts[certId] = value;
|
||||
if (unmarkedKeyEntry != null)
|
||||
{
|
||||
if (keyCerts.Count == 0)
|
||||
{
|
||||
string text2 = Hex.ToHexString(certId.Id);
|
||||
keyCerts[text2] = value;
|
||||
keys[text2] = unmarkedKeyEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
keys["unmarked"] = unmarkedKeyEntry;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (asn1OctetString != null)
|
||||
{
|
||||
string key = Hex.ToHexString(asn1OctetString.GetOctets());
|
||||
keyCerts[key] = value;
|
||||
}
|
||||
if (text != null)
|
||||
{
|
||||
certs[text] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AsymmetricKeyEntry GetKey(string alias)
|
||||
{
|
||||
if (alias == null)
|
||||
{
|
||||
throw new ArgumentNullException("alias");
|
||||
}
|
||||
return (AsymmetricKeyEntry)keys[alias];
|
||||
}
|
||||
|
||||
public bool IsCertificateEntry(string alias)
|
||||
{
|
||||
if (alias == null)
|
||||
{
|
||||
throw new ArgumentNullException("alias");
|
||||
}
|
||||
if (certs[alias] != null)
|
||||
{
|
||||
return keys[alias] == null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsKeyEntry(string alias)
|
||||
{
|
||||
if (alias == null)
|
||||
{
|
||||
throw new ArgumentNullException("alias");
|
||||
}
|
||||
return keys[alias] != null;
|
||||
}
|
||||
|
||||
private IDictionary GetAliasesTable()
|
||||
{
|
||||
IDictionary dictionary = Platform.CreateHashtable();
|
||||
foreach (string key3 in certs.Keys)
|
||||
{
|
||||
dictionary[key3] = "cert";
|
||||
}
|
||||
foreach (string key4 in keys.Keys)
|
||||
{
|
||||
if (dictionary[key4] == null)
|
||||
{
|
||||
dictionary[key4] = "key";
|
||||
}
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
public bool ContainsAlias(string alias)
|
||||
{
|
||||
if (certs[alias] == null)
|
||||
{
|
||||
return keys[alias] != null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public X509CertificateEntry GetCertificate(string alias)
|
||||
{
|
||||
if (alias == null)
|
||||
{
|
||||
throw new ArgumentNullException("alias");
|
||||
}
|
||||
X509CertificateEntry x509CertificateEntry = (X509CertificateEntry)certs[alias];
|
||||
if (x509CertificateEntry == null)
|
||||
{
|
||||
string text = (string)localIds[alias];
|
||||
x509CertificateEntry = ((text == null) ? ((X509CertificateEntry)keyCerts[alias]) : ((X509CertificateEntry)keyCerts[text]));
|
||||
}
|
||||
return x509CertificateEntry;
|
||||
}
|
||||
|
||||
public string GetCertificateAlias(X509Certificate cert)
|
||||
{
|
||||
if (cert == null)
|
||||
{
|
||||
throw new ArgumentNullException("cert");
|
||||
}
|
||||
foreach (object cert2 in certs)
|
||||
{
|
||||
DictionaryEntry dictionaryEntry = (DictionaryEntry)cert2;
|
||||
X509CertificateEntry x509CertificateEntry = (X509CertificateEntry)dictionaryEntry.Value;
|
||||
if (x509CertificateEntry.Certificate.Equals(cert))
|
||||
{
|
||||
return (string)dictionaryEntry.Key;
|
||||
}
|
||||
}
|
||||
foreach (object keyCert in keyCerts)
|
||||
{
|
||||
DictionaryEntry dictionaryEntry2 = (DictionaryEntry)keyCert;
|
||||
X509CertificateEntry x509CertificateEntry2 = (X509CertificateEntry)dictionaryEntry2.Value;
|
||||
if (x509CertificateEntry2.Certificate.Equals(cert))
|
||||
{
|
||||
return (string)dictionaryEntry2.Key;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
IList list = Platform.CreateArrayList();
|
||||
while (x509CertificateEntry != null)
|
||||
{
|
||||
X509Certificate certificate = x509CertificateEntry.Certificate;
|
||||
X509CertificateEntry x509CertificateEntry2 = null;
|
||||
Asn1OctetString extensionValue = certificate.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier);
|
||||
if (extensionValue != null)
|
||||
{
|
||||
AuthorityKeyIdentifier instance = AuthorityKeyIdentifier.GetInstance(Asn1Object.FromByteArray(extensionValue.GetOctets()));
|
||||
if (instance.GetKeyIdentifier() != null)
|
||||
{
|
||||
x509CertificateEntry2 = (X509CertificateEntry)chainCerts[new CertId(instance.GetKeyIdentifier())];
|
||||
}
|
||||
}
|
||||
if (x509CertificateEntry2 == null)
|
||||
{
|
||||
X509Name issuerDN = certificate.IssuerDN;
|
||||
X509Name subjectDN = certificate.SubjectDN;
|
||||
if (!issuerDN.Equivalent(subjectDN))
|
||||
{
|
||||
foreach (CertId key in chainCerts.Keys)
|
||||
{
|
||||
X509CertificateEntry x509CertificateEntry3 = (X509CertificateEntry)chainCerts[key];
|
||||
X509Certificate certificate2 = x509CertificateEntry3.Certificate;
|
||||
X509Name subjectDN2 = certificate2.SubjectDN;
|
||||
if (subjectDN2.Equivalent(issuerDN))
|
||||
{
|
||||
try
|
||||
{
|
||||
certificate.Verify(certificate2.GetPublicKey());
|
||||
x509CertificateEntry2 = x509CertificateEntry3;
|
||||
}
|
||||
catch (InvalidKeyException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
list.Add(x509CertificateEntry);
|
||||
x509CertificateEntry = ((x509CertificateEntry2 == x509CertificateEntry) ? null : x509CertificateEntry2);
|
||||
}
|
||||
X509CertificateEntry[] array = new X509CertificateEntry[list.Count];
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
array[i] = (X509CertificateEntry)list[i];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetCertificateEntry(string alias, X509CertificateEntry certEntry)
|
||||
{
|
||||
if (alias == null)
|
||||
{
|
||||
throw new ArgumentNullException("alias");
|
||||
}
|
||||
if (certEntry == null)
|
||||
{
|
||||
throw new ArgumentNullException("certEntry");
|
||||
}
|
||||
if (keys[alias] != null)
|
||||
{
|
||||
throw new ArgumentException("There is a key entry with the name " + alias + ".");
|
||||
}
|
||||
certs[alias] = certEntry;
|
||||
chainCerts[new CertId(certEntry.Certificate.GetPublicKey())] = certEntry;
|
||||
}
|
||||
|
||||
public void SetKeyEntry(string alias, AsymmetricKeyEntry keyEntry, X509CertificateEntry[] chain)
|
||||
{
|
||||
if (alias == null)
|
||||
{
|
||||
throw new ArgumentNullException("alias");
|
||||
}
|
||||
if (keyEntry == null)
|
||||
{
|
||||
throw new ArgumentNullException("keyEntry");
|
||||
}
|
||||
if (keyEntry.Key.IsPrivate && chain == null)
|
||||
{
|
||||
throw new ArgumentException("No certificate chain for private key");
|
||||
}
|
||||
if (keys[alias] != null)
|
||||
{
|
||||
DeleteEntry(alias);
|
||||
}
|
||||
keys[alias] = keyEntry;
|
||||
certs[alias] = chain[0];
|
||||
for (int i = 0; i != chain.Length; i++)
|
||||
{
|
||||
chainCerts[new CertId(chain[i].Certificate.GetPublicKey())] = chain[i];
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteEntry(string alias)
|
||||
{
|
||||
if (alias == null)
|
||||
{
|
||||
throw new ArgumentNullException("alias");
|
||||
}
|
||||
AsymmetricKeyEntry asymmetricKeyEntry = (AsymmetricKeyEntry)keys[alias];
|
||||
if (asymmetricKeyEntry != null)
|
||||
{
|
||||
keys.Remove(alias);
|
||||
}
|
||||
X509CertificateEntry x509CertificateEntry = (X509CertificateEntry)certs[alias];
|
||||
if (x509CertificateEntry != null)
|
||||
{
|
||||
certs.Remove(alias);
|
||||
chainCerts.Remove(new CertId(x509CertificateEntry.Certificate.GetPublicKey()));
|
||||
}
|
||||
if (asymmetricKeyEntry != null)
|
||||
{
|
||||
string text = (string)localIds[alias];
|
||||
if (text != null)
|
||||
{
|
||||
localIds.Remove(alias);
|
||||
x509CertificateEntry = (X509CertificateEntry)keyCerts[text];
|
||||
}
|
||||
if (x509CertificateEntry != null)
|
||||
{
|
||||
keyCerts.Remove(text);
|
||||
chainCerts.Remove(new CertId(x509CertificateEntry.Certificate.GetPublicKey()));
|
||||
}
|
||||
}
|
||||
if (x509CertificateEntry == null && asymmetricKeyEntry == null)
|
||||
{
|
||||
throw new ArgumentException("no such entry as " + alias);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEntryOfType(string alias, Type entryType)
|
||||
{
|
||||
if ((object)entryType == typeof(X509CertificateEntry))
|
||||
{
|
||||
return IsCertificateEntry(alias);
|
||||
}
|
||||
if ((object)entryType == typeof(AsymmetricKeyEntry))
|
||||
{
|
||||
if (IsKeyEntry(alias))
|
||||
{
|
||||
return GetCertificate(alias) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[Obsolete("Use 'Count' property instead")]
|
||||
public int Size()
|
||||
{
|
||||
return Count;
|
||||
}
|
||||
|
||||
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();
|
||||
foreach (string key2 in keys.Keys)
|
||||
{
|
||||
byte[] array = new byte[20];
|
||||
random.NextBytes(array);
|
||||
AsymmetricKeyEntry asymmetricKeyEntry = (AsymmetricKeyEntry)keys[key2];
|
||||
DerObjectIdentifier oid;
|
||||
Asn1Encodable asn1Encodable;
|
||||
if (password == null)
|
||||
{
|
||||
oid = PkcsObjectIdentifiers.KeyBag;
|
||||
asn1Encodable = PrivateKeyInfoFactory.CreatePrivateKeyInfo(asymmetricKeyEntry.Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
oid = PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag;
|
||||
asn1Encodable = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(keyAlgorithm, password, array, 1024, asymmetricKeyEntry.Key);
|
||||
}
|
||||
Asn1EncodableVector asn1EncodableVector2 = new Asn1EncodableVector();
|
||||
foreach (string bagAttributeKey in asymmetricKeyEntry.BagAttributeKeys)
|
||||
{
|
||||
Asn1Encodable obj = asymmetricKeyEntry[bagAttributeKey];
|
||||
if (!bagAttributeKey.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
|
||||
{
|
||||
asn1EncodableVector2.Add(new DerSequence(new DerObjectIdentifier(bagAttributeKey), new DerSet(obj)));
|
||||
}
|
||||
}
|
||||
asn1EncodableVector2.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(key2))));
|
||||
if (asymmetricKeyEntry[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
|
||||
{
|
||||
X509CertificateEntry certificate = GetCertificate(key2);
|
||||
AsymmetricKeyParameter publicKey = certificate.Certificate.GetPublicKey();
|
||||
SubjectKeyIdentifier obj2 = CreateSubjectKeyID(publicKey);
|
||||
asn1EncodableVector2.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, new DerSet(obj2)));
|
||||
}
|
||||
asn1EncodableVector.Add(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();
|
||||
Pkcs12PbeParams pkcs12PbeParams = new Pkcs12PbeParams(array2, 1024);
|
||||
AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(certAlgorithm, pkcs12PbeParams.ToAsn1Object());
|
||||
ISet set = new HashSet();
|
||||
foreach (string key3 in keys.Keys)
|
||||
{
|
||||
X509CertificateEntry certificate2 = GetCertificate(key3);
|
||||
CertBag certBag = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(certificate2.Certificate.GetEncoded()));
|
||||
Asn1EncodableVector asn1EncodableVector4 = new Asn1EncodableVector();
|
||||
foreach (string bagAttributeKey2 in certificate2.BagAttributeKeys)
|
||||
{
|
||||
Asn1Encodable obj3 = certificate2[bagAttributeKey2];
|
||||
if (!bagAttributeKey2.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
|
||||
{
|
||||
asn1EncodableVector4.Add(new DerSequence(new DerObjectIdentifier(bagAttributeKey2), new DerSet(obj3)));
|
||||
}
|
||||
}
|
||||
asn1EncodableVector4.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(key3))));
|
||||
if (certificate2[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
|
||||
{
|
||||
AsymmetricKeyParameter publicKey2 = certificate2.Certificate.GetPublicKey();
|
||||
SubjectKeyIdentifier obj4 = CreateSubjectKeyID(publicKey2);
|
||||
asn1EncodableVector4.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, new DerSet(obj4)));
|
||||
}
|
||||
asn1EncodableVector3.Add(new SafeBag(PkcsObjectIdentifiers.CertBag, certBag.ToAsn1Object(), new DerSet(asn1EncodableVector4)));
|
||||
set.Add(certificate2.Certificate);
|
||||
}
|
||||
foreach (string key4 in certs.Keys)
|
||||
{
|
||||
X509CertificateEntry x509CertificateEntry = (X509CertificateEntry)certs[key4];
|
||||
if (keys[key4] != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
CertBag certBag2 = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(x509CertificateEntry.Certificate.GetEncoded()));
|
||||
Asn1EncodableVector asn1EncodableVector5 = new Asn1EncodableVector();
|
||||
foreach (string bagAttributeKey3 in x509CertificateEntry.BagAttributeKeys)
|
||||
{
|
||||
if (!bagAttributeKey3.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
|
||||
{
|
||||
Asn1Encodable obj5 = x509CertificateEntry[bagAttributeKey3];
|
||||
if (!bagAttributeKey3.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
|
||||
{
|
||||
asn1EncodableVector5.Add(new DerSequence(new DerObjectIdentifier(bagAttributeKey3), new DerSet(obj5)));
|
||||
}
|
||||
}
|
||||
}
|
||||
asn1EncodableVector5.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(key4))));
|
||||
asn1EncodableVector3.Add(new SafeBag(PkcsObjectIdentifiers.CertBag, certBag2.ToAsn1Object(), new DerSet(asn1EncodableVector5)));
|
||||
set.Add(x509CertificateEntry.Certificate);
|
||||
}
|
||||
foreach (CertId key5 in chainCerts.Keys)
|
||||
{
|
||||
X509CertificateEntry x509CertificateEntry2 = (X509CertificateEntry)chainCerts[key5];
|
||||
if (set.Contains(x509CertificateEntry2.Certificate))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
CertBag certBag3 = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(x509CertificateEntry2.Certificate.GetEncoded()));
|
||||
Asn1EncodableVector asn1EncodableVector6 = new Asn1EncodableVector();
|
||||
foreach (string bagAttributeKey4 in x509CertificateEntry2.BagAttributeKeys)
|
||||
{
|
||||
if (!bagAttributeKey4.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
|
||||
{
|
||||
asn1EncodableVector6.Add(new DerSequence(new DerObjectIdentifier(bagAttributeKey4), new DerSet(x509CertificateEntry2[bagAttributeKey4])));
|
||||
}
|
||||
}
|
||||
asn1EncodableVector3.Add(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 = CryptPbeData(forEncryption: true, algorithmIdentifier, password, wrongPkcs12Zero: false, derEncoded2);
|
||||
EncryptedData encryptedData = new EncryptedData(PkcsObjectIdentifiers.Data, algorithmIdentifier, new BerOctetString(str));
|
||||
contentInfo2 = new ContentInfo(PkcsObjectIdentifiers.EncryptedData, encryptedData.ToAsn1Object());
|
||||
}
|
||||
ContentInfo[] info = new ContentInfo[2] { contentInfo, contentInfo2 };
|
||||
byte[] encoded = new AuthenticatedSafe(info).GetEncoded(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 = CalculatePbeMac(OiwObjectIdentifiers.IdSha1, array3, 1024, password, wrongPkcs12Zero: 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 = ((!useDerEncoding) ? new BerOutputStream(stream) : new DerOutputStream(stream));
|
||||
derOutputStream.WriteObject(obj6);
|
||||
}
|
||||
|
||||
internal static byte[] CalculatePbeMac(DerObjectIdentifier oid, byte[] salt, int itCount, char[] password, bool wrongPkcs12Zero, byte[] data)
|
||||
{
|
||||
Asn1Encodable pbeParameters = PbeUtilities.GenerateAlgorithmParameters(oid, salt, itCount);
|
||||
ICipherParameters parameters = PbeUtilities.GenerateCipherParameters(oid, password, wrongPkcs12Zero, pbeParameters);
|
||||
IMac mac = (IMac)PbeUtilities.CreateEngine(oid);
|
||||
mac.Init(parameters);
|
||||
return MacUtilities.DoFinal(mac, data);
|
||||
}
|
||||
|
||||
private static byte[] CryptPbeData(bool forEncryption, AlgorithmIdentifier algId, char[] password, bool wrongPkcs12Zero, byte[] data)
|
||||
{
|
||||
if (!(PbeUtilities.CreateEngine(algId.Algorithm) is IBufferedCipher bufferedCipher))
|
||||
{
|
||||
throw new Exception("Unknown encryption algorithm: " + algId.Algorithm);
|
||||
}
|
||||
Pkcs12PbeParams instance = Pkcs12PbeParams.GetInstance(algId.Parameters);
|
||||
ICipherParameters parameters = PbeUtilities.GenerateCipherParameters(algId.Algorithm, password, wrongPkcs12Zero, instance);
|
||||
bufferedCipher.Init(forEncryption, parameters);
|
||||
return bufferedCipher.DoFinal(data);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user