无效的提供者类型又指定了一次

时间:2018-08-28 17:10:23

标签: c# visual-studio authentication iis x509certificate

我已经查看了以下问题及其答案:

"Invalid provider type specified" CryptographicException when trying to load private key of certificate

How do I create client certificates for local testing of two-way authentication over SSL?

Invalid provider type specified. CryptographicException

第二个问题所引用的博客。

我怀疑证书颁发者有问题,但我可能是错的。

前言
我是身份验证的新手(您可以看成是白痴)。当前项目是将用Visual Studio 2013 .Net 4.5.1编写的现有网站和Web应用程序升级到Visual Studio 2017 2017 .Net 4.6.1,以满足新消息代理的要求。

环境
Windows 10
Visual Studio 2017(15.8.1)
IIS 10
Microsoft SQL Server 2017

问题描述
用C#编写的Web服务器在身份验证期间抛出此错误

    {"IDX10614: AsymmetricSecurityKey.GetSignatureFormater( 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' ) threw an exception.
Key:
    'System.IdentityModel.Tokens.X509AsymmetricSecurityKey'\nSignatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', check to make sure the     SignatureAlgorithm is supported.\nException:'System.Security.Cryptography.CryptographicException: Invalid provider type specified.
       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)\r\n   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 System.IdentityModel.Tokens.X509AsymmetricSecurityKey.get_PrivateKey()\r\n   at System.IdentityModel.Tokens.X509AsymmetricSecurityKey.GetSignatureFormatter(String algorithm)
       at System.IdentityModel.Tokens.AsymmetricSignatureProvider..ctor(AsymmetricSecurityKey key, String algorithm, Boolean willCreateSignatures)'.
    If you only need to verify signatures the parameter 'willBeUseForSigning' should be false if the private key is not be available."}

已采取的步骤
最初没有要检查的证书,并且生成了另一个错误。
在以管理员身份运行的PowerShell中

New-SelfSignedCertificate-主题“ CN = XxxxxxxXXCA” -DnsName“ localhost” -FriendlyName“ XxxxxxxXXCA” -KeyUsage DigitalSignature -KeyUsageProperty ALL -KeyAlgorithm RSA -KeyLength 2048 -CertStoreLocation“ Cert:\ CurrentUser \ My”

启动MMC

将创建的证书复制到“本地计算机个人”

将证书复制到本地计算机受信任的根证书颁发机构

将证书复制到本地计算机受信任的发布者

在IIS中启动网站

在Visual Studio 2017中运行Web服务器

使用高级REST客户端(ARC)从客户端向服务器发送登录请求。

在下面的代码中遍历Visual Studio 2017调试器中的身份验证代码:

在return语句中引发异常。

    public string GenerateToken(string email)
    {

        X509Store store = new X509Store(StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        var certs = store.Certificates;

        X509Certificate2 signingCert =
        certs.Cast<X509Certificate2>().FirstOrDefault(cert => cert.FriendlyName == "XxxxxxxXXCA");
        SigningCredentials signingCredentials = new X509SigningCredentials(signingCert);

        var tokenHandler = new JwtSecurityTokenHandler();
        var now = DateTime.UtcNow;

        var customer = _customerService.GetCustomerByEmail(email); 

        var emailClaim = new Claim(ClaimTypes.Email, customer.Email, ClaimValueTypes.String);
        var userIdClaim = new Claim(ClaimTypes.NameIdentifier, customer.Id.ToString(), ClaimValueTypes.Integer);
        var roleClaim = new Claim(ClaimTypes.Role, "customer", ClaimValueTypes.String);

        var claimsList = new List<Claim> { emailClaim, userIdClaim, roleClaim };

        var tokenDescriptor = new SecurityTokenDescriptor()
        {
            AppliesToAddress = "http://localhost/api",
            SigningCredentials = signingCredentials,
            TokenIssuerName = "http://localhost",
            Lifetime = new Lifetime(now, now.AddDays(30)),
            //Lifetime = new Lifetime(now, now.AddDays(1)),
            Subject = new ClaimsIdentity(claimsList)
        };

        store.Close();
        return tokenHandler.WriteToken(tokenHandler.CreateToken(tokenDescriptor));
    }

1 个答案:

答案 0 :(得分:2)

New-SelfSignedCertificate cmdlet默认情况下使用密钥存储提供程序。大部分.NET Framework(特别是X509Certificate2)都不支持CNG密钥。结果,当您使用带有存储在CNG中的私钥的证书创建X509Certificate2实例时,get属性上的PrivateKey访问器将引发异常:

at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()

我相信,您不拥有在PrivateKey上调用getter的代码,因此,您需要通过在{{的-Provider参数中显式提供旧提供程序名称来重新创建证书。 1}} cmdlet调用。例如,您可以使用New-SelfSignedCertificate提供程序作为参数值。