Skip to content

Commit

Permalink
Improve use of PAL's RawData for X509Certificate
Browse files Browse the repository at this point in the history
  • Loading branch information
vcsjones committed Jun 22, 2024
1 parent 649626b commit 0262a63
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public void CloneTo(X509Certificate2Collection collection)

private static string GetCertificateHashString(ICertificatePal certPal)
{
return X509Certificate.GetCertHashString(HashAlgorithmName.SHA256, certPal);
return X509Certificate.GetCertHashString(HashAlgorithmName.SHA256, certPal.RawData);
}

private struct EnumCertificatesContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class X509Certificate : IDisposable, IDeserializationCallback, ISerializa
private volatile string? _lazyKeyAlgorithm;
private volatile byte[]? _lazyKeyAlgorithmParameters;
private volatile byte[]? _lazyPublicKey;
private volatile byte[]? _lazyRawData;
private DateTime _lazyNotBefore = DateTime.MinValue;
private DateTime _lazyNotAfter = DateTime.MinValue;

Expand All @@ -37,6 +38,7 @@ public virtual void Reset()
_lazyKeyAlgorithm = null;
_lazyKeyAlgorithmParameters = null;
_lazyPublicKey = null;
_lazyRawData = null;
_lazyNotBefore = DateTime.MinValue;
_lazyNotAfter = DateTime.MinValue;

Expand Down Expand Up @@ -242,6 +244,15 @@ void IDeserializationCallback.OnDeserialization(object? sender)
throw new PlatformNotSupportedException();
}

private protected ReadOnlyMemory<byte> PalRawDataMemory
{
get
{
ThrowIfInvalid();
return _lazyRawData ??= Pal.RawData;
}
}

public IntPtr Handle => Pal is null ? IntPtr.Zero : Pal.Handle;

public string Issuer
Expand Down Expand Up @@ -343,12 +354,7 @@ public virtual byte[] GetCertHash()
public virtual byte[] GetCertHash(HashAlgorithmName hashAlgorithm)
{
ThrowIfInvalid();
return GetCertHash(hashAlgorithm, Pal);
}

private static byte[] GetCertHash(HashAlgorithmName hashAlgorithm, ICertificatePalCore certPal)
{
return CryptographicOperations.HashData(hashAlgorithm, certPal.RawData);
return CryptographicOperations.HashData(hashAlgorithm, PalRawDataMemory.Span);
}

public virtual bool TryGetCertHash(
Expand All @@ -358,7 +364,7 @@ public virtual bool TryGetCertHash(
{
ThrowIfInvalid();

return CryptographicOperations.TryHashData(hashAlgorithm, Pal.RawData, destination, out bytesWritten);
return CryptographicOperations.TryHashData(hashAlgorithm, PalRawDataMemory.Span, destination, out bytesWritten);
}

public virtual string GetCertHashString()
Expand All @@ -370,13 +376,15 @@ public virtual string GetCertHashString()
public virtual string GetCertHashString(HashAlgorithmName hashAlgorithm)
{
ThrowIfInvalid();

return GetCertHashString(hashAlgorithm, Pal);
return GetCertHashString(hashAlgorithm, PalRawDataMemory.Span);
}

internal static string GetCertHashString(HashAlgorithmName hashAlgorithm, ICertificatePalCore certPal)
internal static string GetCertHashString(HashAlgorithmName hashAlgorithm, ReadOnlySpan<byte> rawData)
{
return GetCertHash(hashAlgorithm, certPal).ToHexStringUpper();
Span<byte> buffer = stackalloc byte[64]; // Largest supported hash size is 512 bits

int written = CryptographicOperations.HashData(hashAlgorithm, rawData, buffer);
return Convert.ToHexString(buffer.Slice(0, written));
}

// Only use for internal purposes when the returned byte[] will not be mutated
Expand Down Expand Up @@ -409,7 +417,7 @@ public virtual byte[] GetRawCertData()
{
ThrowIfInvalid();

return Pal.RawData.CloneByteArray();
return PalRawDataMemory.ToArray();
}

public override int GetHashCode()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ namespace System.Security.Cryptography.X509Certificates
{
public class X509Certificate2 : X509Certificate
{
private volatile byte[]? _lazyRawData;
private volatile Oid? _lazySignatureAlgorithm;
private volatile int _lazyVersion;
private volatile X500DistinguishedName? _lazySubjectName;
Expand All @@ -30,7 +29,6 @@ public class X509Certificate2 : X509Certificate

public override void Reset()
{
_lazyRawData = null;
_lazySignatureAlgorithm = null;
_lazyVersion = 0;
_lazySubjectName = null;
Expand Down Expand Up @@ -327,15 +325,7 @@ public PublicKey PublicKey
/// Unlike <see cref="RawData" />, this does not create a fresh copy of the data
/// every time.
/// </remarks>
public ReadOnlyMemory<byte> RawDataMemory
{
get
{
ThrowIfInvalid();

return _lazyRawData ??= Pal.RawData;
}
}
public ReadOnlyMemory<byte> RawDataMemory => PalRawDataMemory;

public string SerialNumber => GetSerialNumberString();

Expand Down

0 comments on commit 0262a63

Please sign in to comment.