如何让ASP.NET访问证书存储中的证书中的私钥?

我有一个ASP.NET应用程序访问证书存储区中的证书中的私钥。 在Windows Server 2003上,我可以使用winhttpcertcfg.exe将私钥访问到NETWORK SERVICE帐户。 如何授予在IIS 7.5网站上访问Windows Server 2008 R2上的证书存储(本地计算机\个人)中的证书中的私钥的权限?

我已经试过使用证书MMC(Server 2008 R2)给“Everyone”,“IIS AppPool \ DefaultAppPool”,“IIS_IUSRS”以及其他安全帐户提供完全信任访问。 但是,下面的代码演示了代码不能访问使用私钥导入的证书的私钥。 每次访问私钥属性时,代码会抛出并出错。

Default.aspx的

  <%@ Page Language =“C#”AutoEventWireup =“true”CodeFile =“Default.aspx.cs”Inherits =“_ Default”%>
 <%@ Import Namespace =“System.Security.Cryptography.X509Certificates”%>
 <!DOCTYPE html PUBLIC“ -  // W3C // DTD XHTML 1.0 Transitional // EN”“ http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ”>
 <html xmlns =“http://www.w3.org/1999/xhtml”>
 <head runat =“server”>
     <TITLE> </ TITLE>
 </ HEAD>
 <BODY>
     <form id =“form1”runat =“server”>
     <DIV>
         <asp:Repeater ID =“repeater1”runat =“server”>
             <HeaderTemplate中>
                 <表>
                     <TR>
                         <TD>
                            证书
                         </ TD>
                         <TD>
                            公钥
                         </ TD>
                         <TD>
                            私钥
                         </ TD>
                     </ TR>
             </ HeaderTemplate中>
             <ItemTemplate中>
                 <TR>
                     <TD>
                     <%#((X509Certificate2)Container.DataItem).GetNameInfo(X509NameType.SimpleName,false)%>
                     </ TD>
                     <TD>
                     <%#((X509Certificate2)Container.DataItem).HasPublicKeyAccess()%>
                     </ TD>
                     <TD>
                     <%#((X509Certificate2)Container.DataItem).HasPrivateKeyAccess()%>
                     </ TD>
                 </ TR>
             </ ItemTemplate中>
             <FooterTemplate>
                 </ TABLE> </ FooterTemplate>
         </ ASP:中继>
     </ DIV>
     </ FORM>
 </ BODY>
 </ HTML> 

Default.aspx.cs

使用系统;
使用System.Security.Cryptography;
使用System.Security.Cryptography.X509Certificates;
使用System.Web.UI;
公共部分类_默认:页面 
 {
    公共X509Certificate2Collection证书;
     protected void Page_Load(object sender,EventArgs e)
     {
         //本地计算机\个人
         var store = new X509Store(StoreLocation.LocalMachine);
         //创build并打开只读访问存储
         store.Open(OpenFlags.ReadOnly);
        证书= store.Certificates;
         repeater1.DataSource =证书;
         repeater1.DataBind();
     }
 }
公共静态类扩展
 {
    公共静态stringHasPublicKeyAccess(这个X509Certificate2证书)
     {
        尝试
         {
             AsymmetricAlgorithm algorithm = cert.PublicKey.Key;
         }
         catch(Exception ex)
         {
            返回“否”;
         }
        返回“是”;
     }
    公共静态stringHasPrivateKeyAccess(这个X509Certificate2证书)
     {
        尝试
         {
            stringalgorithm= cert.PrivateKey.KeyExchangeAlgorithm;
         }
         catch(Exception ex)
         {
            返回“否”;
         }
        返回“是”;
     }
 } 
  1. 创build/购买证书。 确保它有一个私钥。
  2. 将证书导入“本地计算机”帐户。 最好使用证书MMC。 确保选中“允许私钥导出”
  3. 基于此,IIS 7.5应用程序池的身份使用以下之一。

    • IIS 7.5网站正在ApplicationPoolIdentity下运行。 打开MMC =>添加证书(本地计算机)pipe理单元=>证书(本地计算机)=>个人=>证书=>右键单击感兴趣的证书=>所有任务=>pipe理私钥=>添加IIS AppPool\AppPoolName并授予它Full control 。 将“ AppPoolName ”replace为应用程序池的名称(有时是IIS_IUSRS
    • IIS 7.5网站正在NETWORK SERVICE下运行。 使用证书MMC,将“networking服务”添加到“本地计算机\个人”中的完全信任证书。
    • IIS 7.5网站正在“MyIISUser”本地计算机用户帐户下运行。 使用证书MMC,在“本地计算机\个人”中将“MyIISUser”(新本地计算机用户帐户)添加到完全信任证书。

基于@Phil Hale的更新评论:

请注意,如果您使用的是域名,则默认情况下,您的域名将在“从位置”框中被选中。 确保将其更改为“本地计算机”。 将位置更改为“本地计算机”以查看应用程序池标识。

有关通过MMC,Certs,Select Cert,右键单击,所有任务,“pipe理私钥”授予权限的注意事项

pipe理私人密钥只在个人的菜单列表…所以,如果你已经把你的证书放在信任的人等等,你是不走运的。

我们find了解决这个问题的方法。 将证书拖放到个人,执行pipe理私钥的事情来授予权限。 请记住设置为使用对象types的内置插件,并使用本地机器而不是域。 我们授予DefaultAppPool用户的权利,并将其留在那里。

完成之后,将证书拖放回原来的位置。 普雷斯托。

对我来说,只不过是重新导入带有“允许私钥导出”的证书。

我想这是必要的,但它确实让我感到紧张,因为它是访问此证书的第三方应用程序。

我想出了在PowerShell中如何做到这一点,有人问:

 $keyname=(((gci cert:\LocalMachine\my | ? {$_.thumbprint -like $thumbprint}).PrivateKey).CspKeyContainerInfo).UniqueKeyContainerName $keypath = $env:ProgramData + “\Microsoft\Crypto\RSA\MachineKeys\” $fullpath=$keypath+$keyname $Acl = Get-Acl $fullpath $Ar = New-Object System.Security.AccessControl.FileSystemAccessRule("IIS AppPool\$iisAppPoolName", "Read", "Allow") $Acl.SetAccessRule($Ar) Set-Acl $fullpath $Acl