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

我有一个 ASP.NET 应用程序,它可以访问证书存储中证书中的私钥。在 Windows Server 2003上,我能够使用 winhttpcertcfg.exe 为 NETWORK SERVICE 帐户提供私钥访问。如何授权访问 Iis7.5网站 Windows Server 2008 R2的证书存储区(本地计算机个人)中的证书的私钥?

我已经尝试过使用证书 MMC (Server 2008 R2)为“每个人”、“ IIS AppPool DefaultAppPool”、“ IIS _ IUSRS”和所有其他安全帐户提供 Full Trust 访问权限。但是,下面的代码说明该代码不能访问用私钥导入的证书的私钥。相反,每次访问私钥属性时,代码都会抛出和出错。

Default.aspx

<%@Page Language = “ C #”AutoEventWireup = “ true”CodeFile = “ Default.aspx.cs”Heritage its = “ _ Default”% > <%@Page Language = “ C #”AutoEventWireup = “ true”CodeFile = “ Default.aspx.cs”Heritage its = “ _ Default”% > 
<%@Import Namespace = “ System. Security. Cryptography.X509证书”% > 
< DOCTYPE html PUBLIC”-//W3C//DTD XHTML 1.0过渡期//EN”“ http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> 
< html xmlns =”http://www.w3.org/1999/xhtml">  ;
<head runat="server">
< 标题 >  

< 身体 > 
< form id = “ form1”runat = “ server”> 
< div > 
< asp: 转发器 ID = “ repater1”runat = “ server”> 
<HeaderTemplate>
< 表 > 
< tr >
< td > 
证书
 
< td > 
Public Key
</td>
< td > 
私人钥匙
 

</HeaderTemplate>
< 项目模板 > 
<tr>
< td > 
<% # ((X509Cericate2) Container. Dataltem) . GetNameInfo (X509NameType. SimpleName,false)% > 
 
< td > 
<% # ((X509Cericate2) Container. Dataltem) . HasPublicKeyAccess ()% > 
 
<td>
<%#((X509Certificate2)Container.DataItem).HasPrivateKeyAccess() %>
</td>
</tr>
</ItemTemplate>
< FooterTemplate > 
  
 
</html>

Default.aspx.cs

使用系统;
使用系统。保安。密码学;
using System.Security.Cryptography.X509Certificates;
使用 System.Web.UI;
Public 部分 class _ Default: Page
{
公开的 X509证书2收集证书;
Protected void Page _ Load (对象发送器,EventArgs e)
{
// Local Computer\Personal
Var store = new X509Store (StoreLocation. LocalMachine) ;
// create and open store for read-only access
开放(OpenFlags.ReadOnly) ;
证书 = 存储。证书;
DataSource = 证书;
Repater1.DataBind () ;
}
}
公共静态类扩展
{
Public 静态字符串 HasPublicKeyAccess (此 X509Cericate2证书)
{
试试看
{
非对称算法 = cert
}
catch (Exception ex)
{
填报「不」 ;
}
填报「是」 ;
}
Public 静态字符串 HasPrivateKeyAccess (此 X509Cericate2证书)
{
试试看
{
字符串算法 = cert
}
Catch (例外)
{
填报「不」 ;
}
填报「是」 ;
}
}

193433 次浏览
  1. Create / Purchase certificate. Make sure it has a private key.
  2. 将证书导入“本地计算机”帐户。最好使用证书 MMC.确保选中“允许导出私钥”
  3. 基于此,IIS 7.5应用程序池的标识使用下列标识之一。

    • IIS 7.5 Website is running under ApplicationPoolIdentity. Open MMC => Add Certificates (Local computer) snap-in => Certificates (Local Computer) => Personal => Certificates => Right click the certificate of interest => All tasks => Manage private key => Add IIS AppPool\AppPoolName and grant it Full control. Replace "AppPoolName" with the name of your application pool (sometimes IIS_IUSRS)
    • IIS7.5网站在网络服务下运行。使用证书 MMC,在“本地计算机个人”中的证书上将“ NETWORKSERVICE”添加到完全信任。
    • IIS7.5网站以「 MyIISUser 」本地电脑用户帐户运作。使用证书 MMC,将“ MyIISUser”(一个新的本地计算机用户帐户)添加到“本地计算机个人”证书的完全信任中。

根据@Phil Hale 评论更新:

注意,如果你在一个域名上,你的域名将默认选择在“从位置框”。一定要把它改成“本地计算机”。将位置更改为“ LocalComputer”以查看应用程序池身份。

For me, it was nothing more than re-importing the certificate with "Allow private key to be exported" checked.

I guess it is necessary, but it does make me nervous as it is a third party app accessing this certificate.

关于通过 MMC、证书、选择证书、右击、所有任务授予权限的说明,“管理私钥”

管理私人钥匙只是在个人的菜单列表... 所以如果你已经把你的证书在可信任的人,等你的运气。

我们找到了解决这个问题的办法。将证书拖放到“个人”中,执行“管理私钥”以授予权限。记住要设置为使用对象类型的内置函数,并使用本地机器而不是域。我们将权限授予了 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

如果试图从。IIS 中的 pfx 文件的解决方案可能与为 Application Pool启用此选项一样简单。

右键单击 AppPool 并选择 Advanced Settings

然后启用 Load User Profile


enter image description here

补充答案 this is a guide以查找证书的私钥并添加权限。

这是在指南中找到 FindPrivateKey.exe的指南,用于找到证书的私钥。

虽然我参加了以上的活动,但是经过多次尝试,我已经走到了这一步。 1-如果您想从存储中访问证书,您可以以此为例 生成证书并通过一个路径使用它更加容易和干净

Asp.net Core 2.2 OR1:

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;


namespace Tursys.Pool.Storage.Api.Utility
{
class CertificateManager
{
public static X509Certificate2 GetCertificate(string caller)
{
AsymmetricKeyParameter caPrivateKey = null;
X509Certificate2 clientCert;
X509Certificate2 serverCert;


clientCert = GetCertificateIfExist("CN=127.0.0.1", StoreName.My, StoreLocation.LocalMachine);
serverCert = GetCertificateIfExist("CN=MyROOTCA", StoreName.Root, StoreLocation.LocalMachine);
if (clientCert == null || serverCert == null)
{
var caCert = GenerateCACertificate("CN=MyROOTCA", ref caPrivateKey);
addCertToStore(caCert, StoreName.Root, StoreLocation.LocalMachine);


clientCert = GenerateSelfSignedCertificate("CN=127.0.0.1", "CN=MyROOTCA", caPrivateKey);
var p12 = clientCert.Export(X509ContentType.Pfx);


addCertToStore(new X509Certificate2(p12, (string)null, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet), StoreName.My, StoreLocation.LocalMachine);
}


if (caller == "client")
return clientCert;


return serverCert;
}


public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey)
{
const int keyStrength = 2048;


// Generating Random Numbers
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);


// The Certificate Generator
X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();


// Serial Number
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
certificateGenerator.SetSerialNumber(serialNumber);


// Signature Algorithm
//const string signatureAlgorithm = "SHA256WithRSA";
//certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);


// Issuer and Subject Name
X509Name subjectDN = new X509Name(subjectName);
X509Name issuerDN = new X509Name(issuerName);
certificateGenerator.SetIssuerDN(issuerDN);
certificateGenerator.SetSubjectDN(subjectDN);


// Valid For
DateTime notBefore = DateTime.UtcNow.Date;
DateTime notAfter = notBefore.AddYears(2);


certificateGenerator.SetNotBefore(notBefore);
certificateGenerator.SetNotAfter(notAfter);


// Subject Public Key
AsymmetricCipherKeyPair subjectKeyPair;
var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
var keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
subjectKeyPair = keyPairGenerator.GenerateKeyPair();


certificateGenerator.SetPublicKey(subjectKeyPair.Public);


// Generating the Certificate
AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;


ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerKeyPair.Private, random);
// selfsign certificate
Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(signatureFactory);




// correcponding private key
PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);




// merge into X509Certificate2
X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());


Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(info.PrivateKeyAlgorithm.GetDerEncoded());
if (seq.Count != 9)
{
//throw new PemException("malformed sequence in RSA private key");
}


RsaPrivateKeyStructure rsa = RsaPrivateKeyStructure.GetInstance(info.ParsePrivateKey());
RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2, rsa.Coefficient);


try
{
var rsap = DotNetUtilities.ToRSA(rsaparams);
x509 = x509.CopyWithPrivateKey(rsap);


//x509.PrivateKey = ToDotNetKey(rsaparams);
}
catch(Exception ex)
{
;
}
//x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
return x509;


}


public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)
{
var cspParams = new CspParameters
{
KeyContainerName = Guid.NewGuid().ToString(),
KeyNumber = (int)KeyNumber.Exchange,
Flags = CspProviderFlags.UseMachineKeyStore
};


var rsaProvider = new RSACryptoServiceProvider(cspParams);
var parameters = new RSAParameters
{
Modulus = privateKey.Modulus.ToByteArrayUnsigned(),
P = privateKey.P.ToByteArrayUnsigned(),
Q = privateKey.Q.ToByteArrayUnsigned(),
DP = privateKey.DP.ToByteArrayUnsigned(),
DQ = privateKey.DQ.ToByteArrayUnsigned(),
InverseQ = privateKey.QInv.ToByteArrayUnsigned(),
D = privateKey.Exponent.ToByteArrayUnsigned(),
Exponent = privateKey.PublicExponent.ToByteArrayUnsigned()
};


rsaProvider.ImportParameters(parameters);
return rsaProvider;
}


public static X509Certificate2 GenerateCACertificate(string subjectName, ref AsymmetricKeyParameter CaPrivateKey)
{
const int keyStrength = 2048;


// Generating Random Numbers
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);


// The Certificate Generator
X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();


// Serial Number
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
certificateGenerator.SetSerialNumber(serialNumber);


// Signature Algorithm
//const string signatureAlgorithm = "SHA256WithRSA";
//certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);


// Issuer and Subject Name
X509Name subjectDN = new X509Name(subjectName);
X509Name issuerDN = subjectDN;
certificateGenerator.SetIssuerDN(issuerDN);
certificateGenerator.SetSubjectDN(subjectDN);


// Valid For
DateTime notBefore = DateTime.UtcNow.Date;
DateTime notAfter = notBefore.AddYears(2);


certificateGenerator.SetNotBefore(notBefore);
certificateGenerator.SetNotAfter(notAfter);


// Subject Public Key
AsymmetricCipherKeyPair subjectKeyPair;
KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
subjectKeyPair = keyPairGenerator.GenerateKeyPair();


certificateGenerator.SetPublicKey(subjectKeyPair.Public);


// Generating the Certificate
AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;


// selfsign certificate
//Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(issuerKeyPair.Private, random);


ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerKeyPair.Private, random);
// selfsign certificate
Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(signatureFactory);




X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate.GetEncoded());


CaPrivateKey = issuerKeyPair.Private;


return x509;
//return issuerKeyPair.Private;


}


public static bool addCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl)
{
bool bRet = false;


try
{
X509Store store = new X509Store(st, sl);
store.Open(OpenFlags.ReadWrite);
store.Add(cert);


store.Close();
}
catch
{


}


return bRet;
}


protected internal static X509Certificate2 GetCertificateIfExist(string subjectName, StoreName store, StoreLocation location)
{
using (var certStore = new X509Store(store, location))
{
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(
X509FindType.FindBySubjectDistinguishedName, subjectName, false);
X509Certificate2 certificate = null;
if (certCollection.Count > 0)
{
certificate = certCollection[0];
}
return certificate;
}
}


}
}

OR 2:

    services.AddDataProtection()
//.PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp-keys"))
.ProtectKeysWithCertificate(
new X509Certificate2(Path.Combine(Directory.GetCurrentDirectory(), "clientCert.pfx"), "Password")
)
.UnprotectKeysWithAnyCertificate(
new X509Certificate2(Path.Combine(Directory.GetCurrentDirectory(), "clientCert.pfx"), "Password")
);

在证书面板中,右键单击一些证书-> 所有任务-> 管理私钥-> 添加 IIS _ IUSRS User with full control

在我的情况下,我不需要安装带有“允许私钥被导出”选项的证书,就像在其他答案中所说的那样。