0

在这篇 Microsoft文章之后,我们正在访问上传到我们的应用服务的代码中的私钥证书。正如文章所示,我们可以通过其指纹查找证书,并且可以读取它,但是当我们尝试使用以下代码访问其密钥值时,我们会收到错误“CryptographicException:密钥集不存在。”。将密钥转换为 RSACryptoServiceProvider 时发生错误。

此错误消息具有欺骗性,因为我知道密钥集确实存在。在我的非 Azure 开发 VM 上,我可以像任何其他证书一样将私钥文件加载到我的本地计算机证书存储中,并使用相同的代码读取它们的密钥及其值。我确实必须向我的站点在本地运行的用户(IIS 应用程序池标识)授予对证书密钥的访问权限。您可以在 Microsoft 管理控制台中执行此操作(参见图片)。因此我们推测这是一个授权问题。

有人遇到过这种情况么?

授予访问权限

        // 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
        };

堆栈跟踪:22488 21:52:18 错误证书密钥强制转换为 RSACryptoServiceProvider:System.Security.Cryptography.CryptographicException:密钥集不存在

在 System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) 在 System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) 在 System.Security .Cryptography.RSACryptoServiceProvider.GetKeyPair() 在 System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters 参数, Boolean useDefaultKeySize) 在 System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() 在 BCU.Web.Controllers。 CovidLiveAgentController.GetAccessToken() Stacktrace:在 System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) 在 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) 在 System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() 在 BCU.Web.Controllers.CovidLiveAgentController.GetAccessToken()CspParameters 参数,布尔值 useDefaultKeySize) 在 System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() 在 BCU.Web.Controllers.CovidLiveAgentController.GetAccessToken()CspParameters 参数,布尔值 useDefaultKeySize) 在 System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() 在 BCU.Web.Controllers.CovidLiveAgentController.GetAccessToken()

4

1 回答 1

0

首先,永远不要碰X509Certificate2.PrivateKey财产。如果您在 .NET Framework 4.6+ 中,它已过时且不应使用。相反,您需要使用适当的扩展方法来检索基于私钥算法的私钥对象。PrivateKey在我的博客文章中详细了解为什么财产不好: https ://www.pkisolutions.com/accessing-and-using-certificate-private-keys-in-net-framework-net-core/

如果密钥存储在本地机器存储中(而不是当前用户),则执行应用程序的用户帐户必须被授予私钥读取权限。在给定的情况下,您应该将证书加载到 Current User\Personal 存储,而不是参考文章中指定的 Local Machine\Personal 。这消除了密钥权限授予要求

于 2020-08-13T18:09:04.787 回答