인증서 저장소의 인증서에 있는 개인 키에 대한 ASP.NET 액세스 권한을 부여하는 방법은 무엇입니까?
인증서 저장소의 인증서에 있는 개인 키에 액세스하는 ASP.NET 응용 프로그램이 있습니다.Windows Server 2003에서 winhttpcertcfg.exe를 사용하여 NETWORK SERVICE 계정에 대한 개인 키 액세스 권한을 부여할 수 있었습니다.인증서 저장소(로컬 컴퓨터)의 인증서에 있는 개인 키에 액세스할 수 있는 권한을 부여하려면 어떻게 합니까?IIS 7.5 웹 사이트의 Windows Server 2008 R2에서 개인)?
"Everyone", "IIS AppPool\DefaultAppPool", "IIS_IUSRS" 및 인증서 MMC(Server 2008 R2)를 사용하여 찾을 수 있는 다른 모든 보안 계정에 대해 Full Trust 액세스 권한을 부여했습니다.그러나 아래 코드는 개인 키와 함께 가져온 인증서의 개인 키에 대한 액세스 권한이 코드에 없음을 나타냅니다.대신 개인 키 속성에 액세스할 때마다 코드가 느려지고 오류가 발생합니다.
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>
<table>
<tr>
<td>
Cert
</td>
<td>
Public Key
</td>
<td>
Private Key
</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:Repeater>
</div>
</form>
</body>
</html>
Default.aspx.cs
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Web.UI;
public partial class _Default : Page
{
public X509Certificate2Collection Certificates;
protected void Page_Load(object sender, EventArgs e)
{
// Local Computer\Personal
var store = new X509Store(StoreLocation.LocalMachine);
// create and open store for read-only access
store.Open(OpenFlags.ReadOnly);
Certificates = store.Certificates;
repeater1.DataSource = Certificates;
repeater1.DataBind();
}
}
public static class Extensions
{
public static string HasPublicKeyAccess(this X509Certificate2 cert)
{
try
{
AsymmetricAlgorithm algorithm = cert.PublicKey.Key;
}
catch (Exception ex)
{
return "No";
}
return "Yes";
}
public static string HasPrivateKeyAccess(this X509Certificate2 cert)
{
try
{
string algorithm = cert.PrivateKey.KeyExchangeAlgorithm;
}
catch (Exception ex)
{
return "No";
}
return "Yes";
}
}
- 인증서를 생성/구입합니다.개인 키가 있는지 확인합니다.
- 인증서를 "로컬 컴퓨터" 계정으로 가져옵니다.인증서 MMC를 사용하는 것이 가장 좋습니다.개인 키 내보내기 허용을 선택해야 합니다.
이를 기반으로 IIS 7.5 응용 프로그램 풀의 ID는 다음 중 하나를 사용합니다.
- IIS 7.5 웹 사이트가 ApplicationPoolIdentity에서 실행되고 있습니다.MMC => 인증서(로컬 컴퓨터) 스냅인 추가 => 인증서(로컬 컴퓨터) => 개인 => 인증서 => 관심 인증서 마우스 오른쪽 버튼 클릭 => 모든 작업 => 개인 키 관리 => 추가
IIS AppPool\AppPoolName
그리고 그것을 허락합니다.Full control
"AppPoolName"을 응용 프로그램 풀의 이름으로 바꾸기도 합니다(가끔)IIS_IUSRS
) - IIS 7.5 웹 사이트가 네트워크 서비스에서 실행되고 있습니다.인증서 MMC 사용, "로컬 컴퓨터\"의 인증서 전체 신뢰에 "NETWORK SERVICE" 추가개인적인."
- IIS 7.5 웹 사이트가 "내"에서 실행되고 있습니다.IISUser" 로컬 컴퓨터 사용자 계정입니다.인증서 MMC 사용, "내" 추가IISUser"(새 로컬 컴퓨터 사용자 계정)를 "Local Computer\"의 인증서 전체 신뢰에 연결개인적인."
- IIS 7.5 웹 사이트가 ApplicationPoolIdentity에서 실행되고 있습니다.MMC => 인증서(로컬 컴퓨터) 스냅인 추가 => 인증서(로컬 컴퓨터) => 개인 => 인증서 => 관심 인증서 마우스 오른쪽 버튼 클릭 => 모든 작업 => 개인 키 관리 => 추가
@Phil Hale 코멘트를 기반으로 한 업데이트:
도메인에 있는 경우 '위치 상자'에서 도메인이 기본적으로 선택됩니다.이 항목을 "로컬 컴퓨터"로 변경해야 합니다.앱 풀 ID를 보려면 위치를 "로컬 컴퓨터"로 변경합니다.
MMC, 인증서, 인증서 선택, 마우스 오른쪽 단추 클릭, 모든 작업, "개인 키 관리"를 통한 권한 부여에 대한 참고 사항
개인 키 관리는 개인...의 메뉴 목록에만 있습니다.따라서 신뢰할 수 있는 사람 등에 인증서를 넣는다면 운이 없을 것입니다.
우리는 우리에게 효과적인 방법을 찾았습니다.인증서를 개인으로 끌어다 놓고 개인 키 관리 작업을 수행하여 권한을 부여합니다.개체 유형의 기본 제공 기능을 사용하도록 설정하고 도메인이 아닌 로컬 시스템을 사용하도록 설정해야 합니다.DefaultAppPool 사용자에게 권한을 부여하고 그대로 둡니다.
완료되면 인증서를 원래 있던 위치로 드래그 앤 드롭합니다.매우 빠르게.
IIS " .pfx 의 경우 이 옵션을 일 수 .Application Pool
.
후 앱을풀마오버튼로클선릭택고하으른쪽을 선택합니다.Advanced Settings
.
다음 그런다사용을 활성화합니다.Load User Profile
파워셸에서 이걸 어떻게 하는지 알아냈어요 누군가가 물었어요
$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
개인 키 내보내기 허용을 선택한 상태에서 인증서를 다시 가져오는 것에 지나지 않았습니다.
꼭 필요한 것 같은데, 이 인증서에 접속하는 제3자 앱이라 불안하긴 합니다.
위에 참석한 적은 있지만 여러 번 시도한 끝에 이 지경에 이르렀습니다. 1 - 상점에서 인증서에 액세스하려면 이를 예로 들 수 있습니다. 2 - 인증서를 생성하고 경로를 통해 사용하는 것이 훨씬 간편하고 깨끗합니다.
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;
}
}
}
}
또는 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 사용자 추가(전체 제어)
저의 경우, 다른 답변에서 언급한 것처럼 "개인 키 내보내기 허용" 옵션이 선택된 상태에서 인증서를 설치할 필요가 없었습니다.
언급URL : https://stackoverflow.com/questions/2609859/how-to-give-asp-net-access-to-a-private-key-in-a-certificate-in-the-certificate
'sourcecode' 카테고리의 다른 글
CentOS 8.x/7.x/6에 Git의 최신 버전을 설치하는 방법.x (0) | 2023.05.28 |
---|---|
.git는 커밋 후 무시합니다. (0) | 2023.05.28 |
단일 npmrc 파일에 여러 레지스트리를 구성할 수 있는 방법이 있습니까? (0) | 2023.05.28 |
볼륨 믹서 제어 (0) | 2023.05.28 |
xargs로 여러 명령 실행 (0) | 2023.05.28 |