Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
942 views
in Technique[技术] by (71.8m points)

asp.net core - WindowsCryptographicException: Keyset does not exist

I want to create or obtain a certificate, create a pfx-file, load it and have IdentityServer use it. However, IdentityServer is not able to use my pfx.

How to successfully create a pfx and have IdentityServer use it?

I have an IdentityServer4 web solution running on localhost with ASP.Net Core. I am preparing the solution for production running on Azure, and is adding a certificate to the IdentityServer pipeline instead of the developer signing certificate.

Typically this means to swap code like

services.AddIdentityServer()
        .AddDeveloperSigningCredential()

with

services.AddIdentityServer()
        .AddSigningCredential(cert)

where "cert" is an object instance of X509Certificate2 which has loaded a PFX-file containing the certificate (with public and private keys).

The certificate I am using is self signed and is created by following the steps on Ben Cull's Blog https://benjii.me/2017/06/creating-self-signed-certificate-identity-server-azure/

The certicate and private key is exported to a PFX-file in order for both public and private key to be contained in the file.

The loading of the PFX-file succeeds. The code for loading is

cert = new X509Certificate2(Path.Combine(Environment.ContentRootPath, "MyPfxFile.pfx"), "password-used-when-exporting-pfx");

The Pfx-file is located within the web project and is found and read into the X509Certificate object.

When inspecting the X509Certificate2 in Visual Studio the property HasPrivateKey return true, but the PrivateKey property resolves to an exception in the watcher.

'cert.PrivateKey' threw an exception of type 'Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException'

All other properties look sound and good in the watcher.

Also, when I execute the GetRSAPrivateKey in the Immediate Window method on the certificate object instance, it returns an exception.

cert.GetRSAPrivateKey()
'cert.GetRSAPrivateKey()' threw an exception of type 'Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException'
    Data: {System.Collections.ListDictionaryInternal}
    HResult: -2146893798
    HelpLink: null
    InnerException: null
    Message: "Keyset as registered is invalid"
    Source: "System.Security.Cryptography.Csp"
    StackTrace: "   at Internal.NativeCrypto.CapiHelper.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
   at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeProvHandle()
   at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeKeyHandle()
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 keySize, CspParameters parameters, Boolean useDefaultKeySize)
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameters)
   at Internal.Cryptography.Pal.CertificatePal.<>c.<GetRSAPrivateKey>b__61_0(CspParameters csp)
   at Internal.Cryptography.Pal.CertificatePal.GetPrivateKey[T](Func`2 createCsp, Func`2 createCng)
   at Internal.Cryptography.Pal.CertificatePal.GetRSAPrivateKey()
   at Internal.Cryptography.Pal.CertificateExtensionsCommon.GetPrivateKey[T](X509Certificate2 certificate, Predicate`1 matchesConstraints)
   at System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSA
PrivateKey(X509Certificate2 certificate)"
    TargetSite: {System.Security.Cryptography.SafeProvHandle CreateProvHandle(System.Security.Cryptography.CspParameters, Boolean)}

I have tried loading the pfx-file with different settings for X509KeyStorageFlags, but the behaviour and exceptions are the same.

I have also tried to install the PFX into the Windows machine's certificate manager, and I am successfully loading it from there, but the same exceptions are thrown.

At last, when requesting an access token from IdentityServer, the same exception is thrown. I have pasted the exception trace below.

IdentityServer4.Hosting.IdentityServerMiddleware:Critical: Unhandled exception: Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset as registered is invalid
   at Internal.NativeCrypto.CapiHelper.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
   at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeProvHandle()
   at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeKeyHandle()
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 keySize, CspParameters parameters, Boolean useDefaultKeySize)
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameters)
   at Internal.Cryptography.Pal.CertificatePal.<>c.<GetRSAPrivateKey>b__61_0(CspParameters csp)
   at Internal.Cryptography.Pal.CertificatePal.GetPrivateKey[T](Func`2 createCsp, Func`2 createCng)
   at Internal.Cryptography.Pal.CertificatePal.GetRSAPrivateKey()
   at Internal.Cryptography.Pal.CertificateExtensionsCommon.GetPrivateKey[T](X509Certificate2 certificate, Predicate`1 matchesConstraints)
   at System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSAPrivateKey(X509Certificate2 certificate)
   at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_PrivateKey()
   at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_HasPrivateKey()
   at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider.HasPrivateKey(SecurityKey key)
   at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider..ctor(SecurityKey key, String algorithm, Boolean willCreateSignatures)
   at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateSignatureProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures)
   at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateForSigning(SecurityKey key, String algorithm)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.WriteToken(SecurityToken token)
   at IdentityServer4.Services.DefaultTokenCreationService.CreateJwtAsync(JwtSecurityToken jwt) in C:localidentityserver4IdentityServer4srcIdentityServer4ServicesDefaultTokenCreationService.cs:line 209
   at IdentityServer4.Services.DefaultTokenCreationService.<CreateTokenAsync>d__4.MoveNext() in C:localidentityserver4IdentityServer4srcIdentityServer4ServicesDefaultTokenCreationService.cs:line 67
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at IdentityServer4.Services.DefaultTokenService.<CreateSecurityTokenAsync>d__9.MoveNext() in C:localidentityserver4IdentityServer4srcIdentityServer4ServicesDefaultTokenService.cs:line 210
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at IdentityServer4.ResponseHandling.TokenResponseGenerator.<CreateAccessTokenAsync>d__14.MoveNext() in C:localidentityserver4IdentityServer4srcIdentityServer4ResponseHandlingTokenResponseGenerator.cs:line 313
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at IdentityServer4.ResponseHandling.TokenResponseGenerator.<ProcessAuthorizationCodeRequestAsync>d__10.MoveNext() in C:localidentityserver4IdentityServer4srcIdentityServer4ResponseHandlingTokenResponseGenerator.cs:line 133
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at IdentityServer4.ResponseHandling.TokenResponseGenerator.<ProcessAsync>d__7.MoveNext() in C:localidentityserver4IdentityServer4srcIdentityServer4ResponseHandlingTokenResponseGenerator.cs:line 88
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at IdentityServer4.Endpoints.TokenEndpoint.<ProcessTokenRequestAsync>d__7.MoveNext() in C:localidentityserver4IdentityServer4srcIdentityServer4EndpointsTokenEndpoint.cs:line 98
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at IdentityServer4.Endpoints.TokenEndpoint.<ProcessAsync>d__6.MoveNext() in C:localidentityserver4IdentityServer4srcIdentityServer4EndpointsTokenEndpoint.cs:line 70
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at IdentityServer4.Hosting.IdentityServerMiddleware.<Invoke>d__3.MoveNext() in C:localidentityserver4IdentityServer4srcIdentityServer4HostingIdentityServerMiddleware.cs:line 54
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.Message","time":"2018-10-17T09:19:34.1583055Z","tags":{"ai.application.ver":"1.0.0.0","ai.cloud.roleInstance":"HEBE","ai.operation.id":"d7c51fcd-421c862dd08fe813","ai.operation.parentId":"|d7c51fcd-421c862dd08fe813.","ai.operation.name":"POST /connect/token","ai.location.ip":"127.0.0.1","ai.internal.sdkVersion":"aspnet5c:2.1.1","ai.internal.nodeName":"HEBE"},"data":{"baseType":"MessageData","baseData":{"ver":2,"message":"Unhandled exception: Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset as registered is invalid
   at Internal.NativeCrypto.CapiHelper.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
   at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeProvHandle()
   at System.Security.Cryptography.RSACryptoServiceProvider.get_SafeKeyHandle()
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 keySize, CspParameters parameters, Boolean useDefaultKeySize)
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameters)
   at Internal.Cryptography.Pal.CertificatePal.<>c.<GetRSAPrivateKey>b__61_0(CspParameters csp)
   at Internal.Cryptography.Pal.CertificatePal.GetPrivateKey[T](Func`2 createCsp, Func`2 createCng)
   at Internal.Cryptography.Pal.CertificatePal.GetRSAPrivateKey()
   at Internal.Cryptography.Pal.CertificateExtensionsCommon.GetPrivateKey[T](X509Certificate2 certificate, Predicate`1 matchesConstraints)
   at System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSAPrivateKey(X509Certificate2 certificate)
   at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_PrivateKey()
   at Microsoft.IdentityModel.Tokens.X509SecurityKey.get_HasPrivateKey()
   at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider.HasPrivateKey(SecurityKey key)
   at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider..ctor(SecurityKey key, String algorith

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem was resolved by adding IIS_IUSR group. From this link Add group IIS_IUSR:

The problem was that the Permissions for the Private Key of the Certificate in the Windows Certificate Store did not have the IIS_IUSRS group set to allow read access.

Right click certificate -> All Tasks -> Manage Private Keys -> Add group "IIS_IUSRS"


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...