无法创建SignatureProvider,' key.HasPrivateKey'是假的

时间:2018-03-06 04:51:40

标签: identityserver4

我们正在使用IdentityServer4(" http://docs.identityserver.io/en/release/quickstarts/0_overview.html")和EntityFrameworkCore来存储操作和配置数据。要添加签名凭据,我们使用的是x509自签名证书。我们使用以下命令创建x509自签名证书:makecert -r -pe -n "CN=CertName_IdentityServer" -b 01/01/2015 -e 01/01/2039 -eku 1.3.6.1.5.5.7.3.3 -sky signature -a sha256 -len 2048 identityserver.cer。并将此证书添加为解决方案中的嵌入式源。 这是我们的startup.cs文件:

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IConfiguration>(Configuration);

        //connection string
        string connectionString = Configuration.GetConnectionString("IdentityServer");

        var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

        ConfigureSigningCerts(services);

        services.AddIdentityServer()
            // this adds the config data from DB (clients, resources)
            .AddConfigurationStore(options =>
            {
                options.ConfigureDbContext = builder =>
                builder.UseSqlServer(connectionString,
                sql => sql.MigrationsAssembly(migrationsAssembly));
            }) // this adds the operational data from DB (codes, tokens, consents)
            .AddOperationalStore(options =>
            {
                options.ConfigureDbContext = builder =>
                builder.UseSqlServer(connectionString,
            sql => sql.MigrationsAssembly(migrationsAssembly));

                // this enables automatic token cleanup. this is optional.
                options.EnableTokenCleanup = true;
                options.TokenCleanupInterval = 30;
            });
    }
private static void ConfigureSigningCerts(IServiceCollection services)
    {

        var assembly = typeof(Startup).GetTypeInfo().Assembly; 
        /*
        * IdentityServer.WebApi\
        *     Certificates\
        *         identityserver.cer
        * 
        * {assembly name}.{directory}.{file name}
        */
        using (Stream resource = assembly.GetManifestResourceStream("IdentityServer.WebApi.Certificates.identityserver.cer"))
        using (var reader = new BinaryReader(resource))
        {
            var signingCert = new X509Certificate2(reader.ReadBytes((int)resource.Length));


            var keys = new List<SecurityKey>();

            if (signingCert == null) throw new InvalidOperationException("No valid signing certificate could be found.");

            var signingCredential = new SigningCredentials(new X509SecurityKey(signingCert), "RS256");
            services.AddSingleton<ISigningCredentialStore>(new DefaultSigningCredentialsStore(signingCredential));

            var validationCredential = new SigningCredentials(new X509SecurityKey(signingCert), "RS256");
            keys.Add(validationCredential.Key);
            services.AddSingleton<IValidationKeysStore>(new DefaultValidationKeysStore(keys));
        }
    }

当我们在本地主机上执行应用程序时,发现端点工作正常,但在调用connect/token端点时,我们收到以下错误消息:

    crit: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Unhandled exception: System.InvalidOperationException: IDX10638: Cannot created the SignatureProvider, 'key.HasPrivateKey' is false, cannot create signatures. Key: Microsoft.IdentityModel.Tokens.X509SecurityKey.
         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:\local\identity\server4\IdentityServer4\src\IdentityServer4\Services\DefaultTokenCreationService.cs:line 209
         at IdentityServer4.Services.DefaultTokenCreationService.<CreateTokenAsync>d__4.MoveNext() in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\Services\DefaultTokenCreationService.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:\local\identity\server4\IdentityServer4\src\IdentityServer4\Services\DefaultTokenService.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:\local\identity\server4\IdentityServer4\src\IdentityServer4\ResponseHandling\TokenResponseGenerator.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.<ProcessTokenRequestAsync>d__13.MoveNext() in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\ResponseHandling\TokenResponseGenerator.cs:line 249
      --- 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:\local\identity\server4\IdentityServer4\src\IdentityServer4\ResponseHandling\TokenResponseGenerator.cs:line 84
      --- 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:\local\identity\server4\IdentityServer4\src\IdentityServer4\Endpoints\TokenEndpoint.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:\local\identity\server4\IdentityServer4\src\IdentityServer4\Endpoints\TokenEndpoint.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:\local\identity\server4\IdentityServer4\src\IdentityServer4\Hosting\IdentityServerMiddleware.cs:line 54
crit: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Unhandled exception: System.InvalidOperationException: IDX10638: Cannot created the SignatureProvider, 'key.HasPrivateKey' is false, cannot create signatures. Key: Microsoft.IdentityModel.Tokens.X509SecurityKey.
         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:\local\identity\server4\IdentityServer4\src\IdentityServer4\Services\DefaultTokenCreationService.cs:line 209
         at IdentityServer4.Services.DefaultTokenCreationService.<CreateTokenAsync>d__4.MoveNext() in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\Services\DefaultTokenCreationService.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:\local\identity\server4\IdentityServer4\src\IdentityServer4\Services\DefaultTokenService.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:\local\identity\server4\IdentityServer4\src\IdentityServer4\ResponseHandling\TokenResponseGenerator.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.<ProcessTokenRequestAsync>d__13.MoveNext() in C:\local\identity\server4\IdentityServer4\src\IdentityServer4\ResponseHandling\TokenResponseGenerator.cs:line 249
      --- 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:\local\identity\server4\IdentityServer4\src\IdentityServer4\ResponseHandling\TokenResponseGenerator.cs:line 84
      --- 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:\local\identity\server4\IdentityServer4\src\IdentityServer4\Endpoints\TokenEndpoint.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:\local\identity\server4\IdentityServer4\src\IdentityServer4\Endpoints\TokenEndpoint.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:\local\identity\server4\IdentityServer4\src\IdentityServer4\Hosting\IdentityServerMiddleware.cs:line 54

2 个答案:

答案 0 :(得分:1)

如果您使用文件,您可能需要执行其他步骤并指定密码以允许访问私钥。

这应该有希望帮助:How to create a self signed certificate with the private key inside in a file in one simple step?

另一种方法是在本地计算机证书存储中生成证书,然后通过证书管理MMC管理单元将其导出。

答案 1 :(得分:0)

从Powershell(以管理员身份运行Powershell):

$cert = New-SelfSignedCertificate -DnsName yourSiteHere.com -type Custom -CertStoreLocation cert:\localmachine\my -KeyExportPolicy Exportable

使用上述命令,颁发者将成为yourSiteHere,到期日期是默认的一年。它还将具有长度为2048的RSA密钥。 然后,您可以使用certmgr实用程序导出证书(Powershell中还有更多命令可以导出,而我还没有使用过)。 有关更多信息,请参见以下链接:

https://www.petri.com/create-self-signed-certificate-using-powershell

https://docs.microsoft.com/en-us/powershell/module/pkiclient/new-selfsignedcertificate?view=win10-ps

现在,在IdentityServer4中,我扩展了IIdentityServerBuilder类,以提供一种用于从该类型的文件进行证书绑定的方法-很快,如果您有一个静态类,并且它的方法采用“ this someClass”形式的参数,则这是一个“扩展”。您可以扩展任何类,甚至可以扩展C#内部的那些标准类(例如字符串等)。如果执行此操作,则在该类或该类型的变量之后键入句点时,您的方法也将带有Intellisense。这意味着我可以在启动时从构建器访问我的方法(您只需要在Startup.cs中的扩展类的名称空间中放置一个using即可)

public static class SigningCredentialExtension
{
     public static IIdentityServerBuilder GetCertFromAzure(this IIdentityServerBuilder builder)
     {
           //Note:  in order for the certificate to be visible to the app, 
           //an application setting "WEBSITE_LOAD_CERTIFICATES" with the value 
           //of your SSL cert's thumbprint must be added to your IdentityServer
           //webapp on Azure.
           var thumbprint = "your cert's thumbprint";

           var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
           store.Open(OpenFlags.ReadOnly);

           var certs = store.Certificates.Find(X509FindType.FindByThumbprint, 
                    certThumbprint, true);

           if (certs.Count > 0)
           {
                X509Certificate2 cert = 
                       new X509Certificate2(certs[0].Export(X509ContentType.Pfx,
                           "your cert's password"));
                builder.AddSigningCredential(cert);
                builder.AddValidationKey(cert);
           }
           return builder;
     }

     public static IIdentityServerBuilder GetCertFromEmbeddedProjectFile(
                   IIdentityServerBuilder builder)
     {
          var assembly = Assembly.GetExecutingAssembly();
          var fileName = "Your.Project.Namespace.FileName.fileExtension";
          using (Stream stream = assembly.GetManifestResourceStream(resourceName))
          {
                Byte[] raw = new Byte[stream.Length];

                for (Int32 i = 0; i < stream.Length; i++)
                {
                    raw[i] = (Byte)stream.ReadByte();
                }
                X509Certificate2 cert = new X509Certificate2(raw, password);
                builder.AddSigningCredential(cert);
                builder.AddValidationKey(cert);
           }
           return builder;
     }
}

所以-在您的项目中包括上述类,请确保Startup.cs可以看到它(如有必要,请使用),删除您的ConfigureSigningCerts()方法,并在“ services.AddIdentityServer()”行之后输入“。”然后您会在列表中看到扩展方法。使用所需的方法。您无需指定参数,该方法将自动获取构建器。生成器将在之后返回以供以后的方法使用。