diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.StandardProperties.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.StandardProperties.cs index 51584566f560a2..ceb080af407a07 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.StandardProperties.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CngKey.StandardProperties.cs @@ -15,12 +15,14 @@ namespace System.Security.Cryptography /// public sealed partial class CngKey : IDisposable { - // - // Key properties - // - private const int CachedKeySizeUninitializedSentinel = -1; - private int _cachedKeySize = CachedKeySizeUninitializedSentinel; + private volatile int _cachedKeySize = CachedKeySizeUninitializedSentinel; + + private volatile CngAlgorithm? _cachedAlgorithm; + private volatile bool _hasCachedAlgorithmGroup; + private volatile CngAlgorithmGroup? _cachedAlgorithmGroup; + private volatile bool _hasCachedProvider; + private volatile CngProvider? _cachedProvider; /// /// Algorithm group this key can be used with @@ -29,25 +31,38 @@ public CngAlgorithm Algorithm { get { - string algorithm = _keyHandle.GetPropertyAsString(KeyPropertyName.Algorithm, CngPropertyOptions.None)!; - // .NET Framework compat: Don't check for null. Just let CngAlgorithm handle it. - return new CngAlgorithm(algorithm); - } + if (_cachedAlgorithm is null || _keyHandle.IsClosed) + { + string algorithm = _keyHandle.GetPropertyAsString(KeyPropertyName.Algorithm, CngPropertyOptions.None)!; + // .NET Framework compat: Don't check for null. Just let CngAlgorithm handle it. + _cachedAlgorithm = new CngAlgorithm(algorithm); + } + + return _cachedAlgorithm; + } } /// /// Name of the algorithm this key can be used with /// public CngAlgorithmGroup? AlgorithmGroup - { get { - string? algorithmGroup = _keyHandle.GetPropertyAsString(KeyPropertyName.AlgorithmGroup, CngPropertyOptions.None); - if (algorithmGroup == null) - return null; - return new CngAlgorithmGroup(algorithmGroup); + if (!_hasCachedAlgorithmGroup || _keyHandle.IsClosed) + { + string? algorithmGroup = _keyHandle.GetPropertyAsString(KeyPropertyName.AlgorithmGroup, CngPropertyOptions.None); + + if (algorithmGroup is not null) + { + _cachedAlgorithmGroup = new CngAlgorithmGroup(algorithmGroup); + } + + _hasCachedAlgorithmGroup = true; + } + + return _cachedAlgorithmGroup; } } @@ -242,7 +257,6 @@ int ComputeKeySize() /// Usage restrictions on the key /// public CngKeyUsages KeyUsage - { get { @@ -279,10 +293,19 @@ public CngProvider? Provider { get { - string? provider = _providerHandle.GetPropertyAsString(ProviderPropertyName.Name, CngPropertyOptions.None); - if (provider == null) - return null; - return new CngProvider(provider); + if (!_hasCachedProvider || _providerHandle.IsClosed) + { + string? provider = _providerHandle.GetPropertyAsString(ProviderPropertyName.Name, CngPropertyOptions.None); + + if (provider is not null) + { + _cachedProvider = new CngProvider(provider); + } + + _hasCachedProvider = true; + } + + return _cachedProvider; } }