Following this Microsoft article we are accessing a Private Key Certificate in code which was uploaded to our App Service. We can look up the certificate by its thumbprint, as the article indicates, and can read it but when we try to access its key values using the following code we get an error "CryptographicException: Keyset does not exist.". The error occurs when casting the key to RSACryptoServiceProvider.
This error message is deceptive because I know the keyset does exist. On my development VM, non-Azure I can load the Private Key File like any other certificate into my local machines certificate store and using the same code read they key and it’s values. I did have to grant access to the certificate’s key to the user (IIS application pool identity) that my site runs under locally. You can do this in the Microsoft Management Console (see image). Therefore we a speculating that this is a authorization issue.
Has anyone else encountered this?
// private key
if (certificate.HasPrivateKey)
{
try
{
rsa = certificate.PrivateKey as RSACryptoServiceProvider;
}
catch (Exception e)
{
var message = $"Certificate key cast to RSACryptoServiceProvider: {e.ToString()} Stacktrace: {e.StackTrace}";
Error.LogError(message);
throw new Exception(message);
}
}
if (rsa is null)
{
var message = $"Certificate with thumbprint {certificate.Thumbprint} contains no private key.";
Error.LogError(message);
throw new Exception(message);
}
// signiture
var cspParam = new CspParameters
{
KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName,
KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2
};
Stack Trace: 22488 21:52:18 ERROR Certificate key cast to RSACryptoServiceProvider: System.Security.Cryptography.CryptographicException: Keyset does not exist
at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize) at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() at BCU.Web.Controllers.CovidLiveAgentController.GetAccessToken() Stacktrace: at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize) at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() at BCU.Web.Controllers.CovidLiveAgentController.GetAccessToken()