From 068ba8eba9787bb180878561d443abcf6133be9f Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Fri, 5 Apr 2024 11:49:43 -0400 Subject: [PATCH] Improve error when private key is missing in RSABCrypt CNG bcrypt gives an unhelpful error when a public key used in a way that requires the private key. RSABCrypt knows if the key is public or not so we can use this to throw a more helpful exception. --- .../System/Security/Cryptography/RSABCrypt.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSABCrypt.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSABCrypt.cs index c5ac24ab029b2..6e1fbbdb23d91 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSABCrypt.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSABCrypt.cs @@ -20,6 +20,7 @@ internal sealed class RSABCrypt : RSA private SafeBCryptKeyHandle? _key; private int _lastKeySize; + private bool _publicOnly; internal RSABCrypt() { @@ -51,11 +52,11 @@ private SafeBCryptKeyHandle GetKey() SafeBCryptKeyHandle newKey = Interop.BCrypt.BCryptGenerateKeyPair(s_algHandle, keySize); Interop.BCrypt.BCryptFinalizeKeyPair(newKey); - SetKey(newKey); + SetKey(newKey, publicOnly: false); return newKey; } - private void SetKey(SafeBCryptKeyHandle newKey) + private void SetKey(SafeBCryptKeyHandle newKey, bool publicOnly) { Debug.Assert(!newKey.IsInvalid); @@ -65,6 +66,7 @@ private void SetKey(SafeBCryptKeyHandle newKey) SafeBCryptKeyHandle? oldKey = Interlocked.Exchange(ref _key, newKey); ForceSetKeySize(keySize); + _publicOnly = publicOnly; oldKey?.Dispose(); } @@ -112,7 +114,7 @@ public override void ImportParameters(RSAParameters parameters) CryptoPool.Return(keyBlob); } - SetKey(newKey); + SetKey(newKey, publicOnly: parameters.D is null); } public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) @@ -190,6 +192,8 @@ public override bool TryDecrypt( throw new CryptographicException(SR.Cryptography_RSA_DecryptWrongSize); } + ThrowIfPublicOnly(); + switch (padding.Mode) { case RSAEncryptionPaddingMode.Pkcs1: @@ -261,6 +265,7 @@ public override bool TrySignHash( string? hashAlgorithmName = hashAlgorithm.Name; ArgumentException.ThrowIfNullOrEmpty(hashAlgorithmName, nameof(hashAlgorithm)); ArgumentNullException.ThrowIfNull(padding); + ThrowIfPublicOnly(); SafeBCryptKeyHandle key = GetKey(); @@ -426,5 +431,13 @@ private void ThrowIfDisposed() { ObjectDisposedException.ThrowIf(_lastKeySize < 0, this); } + + private void ThrowIfPublicOnly() + { + if (_publicOnly) + { + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); + } + } } }