Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Merge pull request #5922 from stephentoub/x509_perf
Browse files Browse the repository at this point in the history
Improve X509Chain.Build perf on Unix
  • Loading branch information
stephentoub committed Feb 6, 2016
2 parents 2bf9141 + f7f280b commit 1bc77b7
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ public static bool ReleaseSafeX509ChainHandle(IntPtr handle)
}

TimeSpan remainingDownloadTime = timeout;
X509Certificate2 leaf = new X509Certificate2(cert.Handle);
List<X509Certificate2> downloaded = new List<X509Certificate2>();
List<X509Certificate2> systemTrusted = new List<X509Certificate2>();
var leaf = new X509Certificate2(cert.Handle);
var downloaded = new HashSet<X509Certificate2>();
var systemTrusted = new HashSet<X509Certificate2>();

List<X509Certificate2> candidates = OpenSslX509ChainProcessor.FindCandidates(
HashSet<X509Certificate2> candidates = OpenSslX509ChainProcessor.FindCandidates(
leaf,
extraStore,
downloaded,
Expand Down Expand Up @@ -77,7 +77,7 @@ public static bool ReleaseSafeX509ChainHandle(IntPtr handle)

private static void SaveIntermediateCertificates(
X509ChainElement[] chainElements,
List<X509Certificate2> downloaded)
HashSet<X509Certificate2> downloaded)
{
List<X509Certificate2> chainDownloaded = new List<X509Certificate2>(chainElements.Length);

Expand Down Expand Up @@ -110,11 +110,11 @@ public static bool ReleaseSafeX509ChainHandle(IntPtr handle)
return;
}

for (int i = 0; i < chainDownloaded.Count; i++)
foreach (X509Certificate2 cert in chainDownloaded)
{
try
{
userIntermediate.Add(downloaded[i]);
userIntermediate.Add(cert);
}
catch (CryptographicException)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ public SafeX509ChainHandle SafeHandle

public static IChainPal BuildChain(
X509Certificate2 leaf,
List<X509Certificate2> candidates,
List<X509Certificate2> downloaded,
List<X509Certificate2> systemTrusted,
HashSet<X509Certificate2> candidates,
HashSet<X509Certificate2> downloaded,
HashSet<X509Certificate2> systemTrusted,
OidCollection applicationPolicy,
OidCollection certificatePolicy,
X509RevocationMode revocationMode,
Expand Down Expand Up @@ -471,15 +471,15 @@ private static X509ChainStatusFlags MapVerifyErrorToChainStatus(Interop.Crypto.X
}
}

internal static List<X509Certificate2> FindCandidates(
internal static HashSet<X509Certificate2> FindCandidates(
X509Certificate2 leaf,
X509Certificate2Collection extraStore,
List<X509Certificate2> downloaded,
List<X509Certificate2> systemTrusted,
HashSet<X509Certificate2> downloaded,
HashSet<X509Certificate2> systemTrusted,
ref TimeSpan remainingDownloadTime)
{
List<X509Certificate2> candidates = new List<X509Certificate2>();
Queue<X509Certificate2> toProcess = new Queue<X509Certificate2>();
var candidates = new HashSet<X509Certificate2>();
var toProcess = new Queue<X509Certificate2>();
toProcess.Enqueue(leaf);

using (var systemRootStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine))
Expand Down Expand Up @@ -520,12 +520,9 @@ private static X509ChainStatusFlags MapVerifyErrorToChainStatus(Interop.Crypto.X
{
X509Certificate2 current = toProcess.Dequeue();

if (!candidates.Contains(current))
{
candidates.Add(current);
}
candidates.Add(current);

List<X509Certificate2> results = FindIssuer(
HashSet<X509Certificate2> results = FindIssuer(
current,
storesToCheck,
downloaded,
Expand All @@ -547,10 +544,10 @@ private static X509ChainStatusFlags MapVerifyErrorToChainStatus(Interop.Crypto.X
return candidates;
}

private static List<X509Certificate2> FindIssuer(
private static HashSet<X509Certificate2> FindIssuer(
X509Certificate2 cert,
X509Certificate2Collection[] stores,
List<X509Certificate2> downloadedCerts,
HashSet<X509Certificate2> downloadedCerts,
ref TimeSpan remainingDownloadTime)
{
if (IsSelfSigned(cert))
Expand All @@ -563,7 +560,7 @@ private static X509ChainStatusFlags MapVerifyErrorToChainStatus(Interop.Crypto.X

foreach (X509Certificate2Collection store in stores)
{
List<X509Certificate2> fromStore = null;
HashSet<X509Certificate2> fromStore = null;

foreach (X509Certificate2 candidate in store)
{
Expand All @@ -575,13 +572,10 @@ private static X509ChainStatusFlags MapVerifyErrorToChainStatus(Interop.Crypto.X
{
if (fromStore == null)
{
fromStore = new List<X509Certificate2>();
fromStore = new HashSet<X509Certificate2>();
}

if (!fromStore.Contains(candidate))
{
fromStore.Add(candidate);
}
fromStore.Add(candidate);
}
}

Expand Down Expand Up @@ -614,7 +608,7 @@ private static X509ChainStatusFlags MapVerifyErrorToChainStatus(Interop.Crypto.X
{
downloadedCerts.Add(downloaded);

return new List<X509Certificate2>(1) { downloaded };
return new HashSet<X509Certificate2>() { downloaded };
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,9 @@ public virtual bool Equals(X509Certificate other)
if (!Issuer.Equals(other.Issuer))
return false;

byte[] thisSerialNumber = GetSerialNumber();
byte[] otherSerialNumber = other.GetSerialNumber();
byte[] thisSerialNumber = GetRawSerialNumber();
byte[] otherSerialNumber = other.GetRawSerialNumber();

if (thisSerialNumber.Length != otherSerialNumber.Length)
return false;
for (int i = 0; i < thisSerialNumber.Length; i++)
Expand Down Expand Up @@ -179,12 +180,13 @@ public virtual byte[] Export(X509ContentType contentType, string password)
public virtual byte[] GetCertHash()
{
ThrowIfInvalid();
return GetRawCertHash().CloneByteArray();
}

byte[] certHash = _lazyCertHash;
if (certHash == null)
_lazyCertHash = certHash = Pal.Thumbprint;

return certHash.CloneByteArray();
// Only use for internal purposes when the returned byte[] will not be mutated
private byte[] GetRawCertHash()
{
return _lazyCertHash ?? (_lazyCertHash = Pal.Thumbprint);
}

public virtual string GetFormat()
Expand All @@ -197,7 +199,7 @@ public override int GetHashCode()
if (Pal == null)
return 0;

byte[] thumbPrint = GetCertHash();
byte[] thumbPrint = GetRawCertHash();
int value = 0;
for (int i = 0; i < thumbPrint.Length && i < 4; ++i)
{
Expand Down Expand Up @@ -248,10 +250,13 @@ public virtual byte[] GetSerialNumber()
{
ThrowIfInvalid();

byte[] serialNumber = _lazySerialNumber;
if (serialNumber == null)
serialNumber = _lazySerialNumber = Pal.SerialNumber;
return serialNumber.CloneByteArray();
return GetRawSerialNumber().CloneByteArray();
}

// Only use for internal purposes when the returned byte[] will not be mutated
private byte[] GetRawSerialNumber()
{
return _lazySerialNumber ?? (_lazySerialNumber = Pal.SerialNumber);
}

public override string ToString()
Expand Down Expand Up @@ -302,7 +307,7 @@ public virtual string ToString(bool fVerbose)
sb.AppendLine();
sb.AppendLine("[Thumbprint]");
sb.Append(" ");
sb.Append(GetCertHash().ToHexArrayUpper());
sb.Append(GetRawCertHash().ToHexArrayUpper());
sb.AppendLine();

return sb.ToString();
Expand Down

0 comments on commit 1bc77b7

Please sign in to comment.