Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 9d212e9

Browse files
committed
Merge pull request #2007 from stephentoub/cert_allocs
Remove some allocations from X509 library
2 parents 2e5bd3f + a46da94 commit 9d212e9

20 files changed

+228
-170
lines changed

src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Helpers.cs

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
5-
using System.Text;
65
using System.Diagnostics;
76
using System.Globalization;
8-
using System.Security.Cryptography;
97

108
namespace Internal.Cryptography
119
{
@@ -16,59 +14,54 @@ public static byte[] CloneByteArray(this byte[] src)
1614
return (byte[])(src.Clone());
1715
}
1816

19-
// Encode a byte array as an upper case hex string.
20-
public static String ToHexStringUpper(this byte[] bytes)
17+
// Encode a byte array as an array of upper-case hex characters.
18+
public static char[] ToHexArrayUpper(this byte[] bytes)
2119
{
22-
StringBuilder sb = new StringBuilder(bytes.Length * 2);
20+
char[] chars = new char[bytes.Length * 2];
21+
int i = 0;
2322
foreach (byte b in bytes)
2423
{
25-
sb.AppendFormat("{0:X2}", b);
24+
chars[i++] = NibbleToHex((byte)(b >> 4));
25+
chars[i++] = NibbleToHex((byte)(b & 0xF));
2626
}
27-
return sb.ToString();
27+
return chars;
28+
}
29+
30+
// Encode a byte array as an upper case hex string.
31+
public static string ToHexStringUpper(this byte[] bytes)
32+
{
33+
return new string(ToHexArrayUpper(bytes));
2834
}
2935

3036
// Decode a hex string-encoded byte array passed to various X509 crypto api. The parsing rules are overly forgiving but for compat reasons,
3137
// they cannot be tightened.
32-
public static byte[] DecodeHexString(this String s)
38+
public static byte[] DecodeHexString(this string s)
3339
{
34-
String hexString = DiscardWhiteSpaces(s);
35-
uint cbHex = (uint)hexString.Length / 2;
36-
byte[] hex = new byte[cbHex];
37-
int i = 0;
38-
for (int index = 0; index < cbHex; index++)
40+
int whitespaceCount = 0;
41+
42+
for (int i = 0; i < s.Length; i++)
3943
{
40-
hex[index] = (byte)((HexToByte(hexString[i]) << 4) | HexToByte(hexString[i + 1]));
41-
i += 2;
44+
if (char.IsWhiteSpace(s[i]))
45+
whitespaceCount++;
4246
}
43-
return hex;
44-
}
4547

46-
private static String DiscardWhiteSpaces(String inputBuffer)
47-
{
48-
return DiscardWhiteSpaces(inputBuffer, 0, inputBuffer.Length);
49-
}
48+
uint cbHex = (uint)(s.Length - whitespaceCount) / 2;
49+
byte[] hex = new byte[cbHex];
5050

51-
private static String DiscardWhiteSpaces(String inputBuffer, int inputOffset, int inputCount)
52-
{
53-
int i, iCount = 0;
54-
for (i = 0; i < inputCount; i++)
51+
for (int index = 0, i = 0; index < cbHex; index++)
5552
{
56-
if (Char.IsWhiteSpace(inputBuffer[inputOffset + i]))
53+
if (char.IsWhiteSpace(s[i]))
5754
{
58-
iCount++;
55+
i++;
5956
}
60-
}
61-
62-
char[] rgbOut = new char[inputCount - iCount];
63-
iCount = 0;
64-
for (i = 0; i < inputCount; i++)
65-
{
66-
if (!Char.IsWhiteSpace(inputBuffer[inputOffset + i]))
57+
else
6758
{
68-
rgbOut[iCount++] = inputBuffer[inputOffset + i];
59+
hex[index] = (byte)((HexToByte(s[i]) << 4) | HexToByte(s[i + 1]));
60+
i += 2;
6961
}
7062
}
71-
return new String(rgbOut);
63+
64+
return hex;
7265
}
7366

7467
private static byte HexToByte(char val)
@@ -83,6 +76,14 @@ private static byte HexToByte(char val)
8376
return 0xFF;
8477
}
8578

79+
private static char NibbleToHex(byte b)
80+
{
81+
Debug.Assert(b >= 0 && b <= 15);
82+
return (char)(b >= 0 && b <= 9 ?
83+
'0' + b :
84+
'A' + (b - 10));
85+
}
86+
8687
public static bool ContentsEqual(this byte[] a1, byte[] a2)
8788
{
8889
if (a1.Length != a2.Length)
@@ -115,5 +116,3 @@ private static bool IsValidYear(this Calendar calendar, int year, int era)
115116
}
116117
}
117118
}
118-
119-

src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.PrivateKey.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public AsymmetricAlgorithm PrivateKey
4141
// We never want to stomp over certificate private keys.
4242
cspParameters.Flags |= CspProviderFlags.UseExistingKey;
4343

44-
int algId = OidInfo.FindOidInfo(CryptOidInfoKeyType.CRYPT_OID_INFO_OID_KEY, this.KeyAlgorithm, OidGroup.PublicKeyAlgorithm, fallBackToAllGroups: true).AlgId;
44+
int algId = OidInfo.FindOidInfo(CryptOidInfoKeyType.CRYPT_OID_INFO_OID_KEY, KeyAlgorithm, OidGroup.PublicKeyAlgorithm, fallBackToAllGroups: true).AlgId;
4545
switch (algId)
4646
{
4747
case AlgId.CALG_RSA_KEYX:

src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/CertificatePal.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ public void AppendPrivateKeyInfo(StringBuilder sb)
396396
CspKeyContainerInfo cspKeyContainerInfo = null;
397397
try
398398
{
399-
if (this.HasPrivateKey)
399+
if (HasPrivateKey)
400400
{
401401
CspParameters parameters = GetPrivateKey();
402402
cspKeyContainerInfo = new CspKeyContainerInfo(parameters);

src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/StorePal.Find.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ private static void ValidateOidValue(String keyValue)
449449
for (int i = 1; i < len; i++)
450450
{
451451
// ensure every character is either a digit or a dot
452-
if (Char.IsDigit(keyValue[i]))
452+
if (char.IsDigit(keyValue[i]))
453453
continue;
454454
if (keyValue[i] != '.' || keyValue[i + 1] == '.') // disallow double dots
455455
throw new ArgumentException(SR.Argument_InvalidOidValue);

src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/PublicKey.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ public sealed class PublicKey
1818
public PublicKey(Oid oid, AsnEncodedData parameters, AsnEncodedData keyValue)
1919
{
2020
_oid = new Oid(oid);
21-
this.EncodedParameters = new AsnEncodedData(parameters);
22-
this.EncodedKeyValue = new AsnEncodedData(keyValue);
21+
EncodedParameters = new AsnEncodedData(parameters);
22+
EncodedKeyValue = new AsnEncodedData(keyValue);
2323
return;
2424
}
2525

@@ -33,7 +33,7 @@ public AsymmetricAlgorithm Key
3333
{
3434
AsymmetricAlgorithm key = _lazyKey;
3535
if (key == null)
36-
key = _lazyKey = X509Pal.Instance.DecodePublicKey(this.Oid, this.EncodedKeyValue.RawData, this.EncodedParameters.RawData);
36+
key = _lazyKey = X509Pal.Instance.DecodePublicKey(Oid, EncodedKeyValue.RawData, EncodedParameters.RawData);
3737
return key;
3838
}
3939
}

src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X500DistinguishedName.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ public String Name
5858
public String Decode(X500DistinguishedNameFlags flag)
5959
{
6060
ThrowIfInvalid(flag);
61-
return X509Pal.Instance.X500DistinguishedNameDecode(this.RawData, flag);
61+
return X509Pal.Instance.X500DistinguishedNameDecode(RawData, flag);
6262
}
6363

6464
public override String Format(bool multiLine)
6565
{
66-
return X509Pal.Instance.X500DistinguishedNameFormat(this.RawData, multiLine);
66+
return X509Pal.Instance.X500DistinguishedNameFormat(RawData, multiLine);
6767
}
6868

6969
private static byte[] Encode(String distinguishedName, X500DistinguishedNameFlags flags)

src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509BasicConstraintsExtension.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@ private static byte[] EncodeExtension(bool certificateAuthority, bool hasPathLen
8282
private void DecodeExtension()
8383
{
8484
if (Oid.Value == Oids.BasicConstraints)
85-
X509Pal.Instance.DecodeX509BasicConstraintsExtension(this.RawData, out _certificateAuthority, out _hasPathLenConstraint, out _pathLenConstraint);
85+
X509Pal.Instance.DecodeX509BasicConstraintsExtension(RawData, out _certificateAuthority, out _hasPathLenConstraint, out _pathLenConstraint);
8686
else
87-
X509Pal.Instance.DecodeX509BasicConstraints2Extension(this.RawData, out _certificateAuthority, out _hasPathLenConstraint, out _pathLenConstraint);
87+
X509Pal.Instance.DecodeX509BasicConstraints2Extension(RawData, out _certificateAuthority, out _hasPathLenConstraint, out _pathLenConstraint);
8888

8989
_decoded = true;
9090
}

src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -125,21 +125,21 @@ public override bool Equals(Object obj)
125125
X509Certificate other = obj as X509Certificate;
126126
if (other == null)
127127
return false;
128-
return this.Equals(other);
128+
return Equals(other);
129129
}
130130

131131
public virtual bool Equals(X509Certificate other)
132132
{
133133
if (other == null)
134134
return false;
135135

136-
if (this.Pal == null)
136+
if (Pal == null)
137137
return other.Pal == null;
138138

139-
if (!this.Issuer.Equals(other.Issuer))
139+
if (!Issuer.Equals(other.Issuer))
140140
return false;
141141

142-
byte[] thisSerialNumber = this.GetSerialNumber();
142+
byte[] thisSerialNumber = GetSerialNumber();
143143
byte[] otherSerialNumber = other.GetSerialNumber();
144144
if (thisSerialNumber.Length != otherSerialNumber.Length)
145145
return false;
@@ -262,32 +262,44 @@ public virtual String ToString(bool fVerbose)
262262
StringBuilder sb = new StringBuilder();
263263

264264
// Subject
265-
sb.Append("[Subject]" + Environment.NewLine + " ");
266-
sb.Append(this.Subject);
265+
sb.AppendLine("[Subject]");
266+
sb.Append(" ");
267+
sb.AppendLine(Subject);
267268

268269
// Issuer
269-
sb.Append(Environment.NewLine + Environment.NewLine + "[Issuer]" + Environment.NewLine + " ");
270-
sb.Append(this.Issuer);
270+
sb.AppendLine();
271+
sb.AppendLine("[Issuer]");
272+
sb.Append(" ");
273+
sb.AppendLine(Issuer);
271274

272275
// Serial Number
273-
sb.Append(Environment.NewLine + Environment.NewLine + "[Serial Number]" + Environment.NewLine + " ");
274-
byte[] serialNumber = this.GetSerialNumber();
276+
sb.AppendLine();
277+
sb.AppendLine("[Serial Number]");
278+
sb.Append(" ");
279+
byte[] serialNumber = GetSerialNumber();
275280
Array.Reverse(serialNumber);
276-
sb.Append(serialNumber.ToHexStringUpper());
281+
sb.Append(serialNumber.ToHexArrayUpper());
282+
sb.AppendLine();
277283

278284
// NotBefore
279-
sb.Append(Environment.NewLine + Environment.NewLine + "[Not Before]" + Environment.NewLine + " ");
280-
sb.Append(FormatDate(this.GetNotBefore()));
285+
sb.AppendLine();
286+
sb.AppendLine("[Not Before]");
287+
sb.Append(" ");
288+
sb.AppendLine(FormatDate(GetNotBefore()));
281289

282290
// NotAfter
283-
sb.Append(Environment.NewLine + Environment.NewLine + "[Not After]" + Environment.NewLine + " ");
284-
sb.Append(FormatDate(this.GetNotAfter()));
291+
sb.AppendLine();
292+
sb.AppendLine("[Not After]");
293+
sb.Append(" ");
294+
sb.AppendLine(FormatDate(GetNotAfter()));
285295

286296
// Thumbprint
287-
sb.Append(Environment.NewLine + Environment.NewLine + "[Thumbprint]" + Environment.NewLine + " ");
288-
sb.Append(this.GetCertHash().ToHexStringUpper());
297+
sb.AppendLine();
298+
sb.AppendLine("[Thumbprint]");
299+
sb.Append(" ");
300+
sb.Append(GetCertHash().ToHexArrayUpper());
301+
sb.AppendLine();
289302

290-
sb.Append(Environment.NewLine);
291303
return sb.ToString();
292304
}
293305

@@ -362,4 +374,3 @@ internal static String FormatDate(DateTime date)
362374
private const X509KeyStorageFlags KeyStorageFlagsAll = (X509KeyStorageFlags)0x1f;
363375
}
364376
}
365-

0 commit comments

Comments
 (0)