Sertifika deposundaki bir sertifikadaki özel bir anahtara ASP.NET erişimi nasıl verilir?


111

Sertifika deposundaki bir sertifikadaki özel anahtara erişen bir ASP.NET uygulamam var. Windows Server 2003'te, NETWORK SERVICE hesabına özel anahtar erişimi sağlamak için winhttpcertcfg.exe'yi kullanabildim. Bir IIS 7.5 web sitesinde bir Windows Server 2008 R2 üzerindeki sertifika deposundaki (Yerel Bilgisayar \ Kişisel) bir sertifikadaki bir Özel Anahtara erişim izinlerini nasıl verebilirim?

"Herkes", "IIS AppPool \ DefaultAppPool", "IIS_IUSRS" ve Sertifikalar MMC'yi (Server 2008 R2) kullanarak bulabildiğim diğer tüm güvenlik hesaplarına Tam Güven erişimi vermeyi denedim. Ancak aşağıdaki kod, kodun, özel anahtarla içe aktarılan bir sertifikanın Özel Anahtarına erişimi olmadığını göstermektedir. Bunun yerine, özel anahtar özelliğine her erişildiğinde kod atar ve hata verir.

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";
    }
}

Yanıtlar:


195
  1. Sertifika oluştur / satın al. Özel anahtarı olduğundan emin olun.
  2. Sertifikayı "Yerel Bilgisayar" hesabına alın. En iyi kullanım Sertifikaları MMC. "Özel anahtarın dışa aktarılmasına izin ver" seçeneğini işaretlediğinizden emin olun.
  3. Hangisine bağlı olarak, IIS 7.5 Uygulama Havuzunun kimliği aşağıdakilerden birini kullanır.

    • IIS 7.5 Web Sitesi, ApplicationPoolIdentity altında çalışıyor. MMC'yi açın => Sertifikalar Ekle (Yerel bilgisayar) ek bileşeni => Sertifikalar (Yerel Bilgisayar) => Kişisel => Sertifikalar => İlgilendiğiniz sertifikayı sağ tıklayın => Tüm görevler => Özel anahtarı yönet => Ekle IIS AppPool\AppPoolNameve verin Full control. " UygulamaHavuzuAdı " nı uygulama havuzunuzun adıyla değiştirin (bazen IIS_IUSRS)
    • IIS 7.5 Web Sitesi NETWORK SERVICE altında çalışmaktadır. Sertifikalar MMC kullanılarak, "Yerel Bilgisayar \ Kişisel" içindeki sertifika için Tam Güven'e "AĞ HİZMETİ" eklendi.
    • IIS 7.5 Web sitesi "MyIISUser" yerel bilgisayar kullanıcı hesabı altında çalışıyor. Sertifikalar MMC kullanılarak, "Yerel Bilgisayar \ Kişisel" içindeki sertifika üzerinde Tam Güven'e "MyIISUser" (yeni bir yerel bilgisayar kullanıcı hesabı) eklendi.

@ Phil Hale yorumuna dayalı güncelleme:

Dikkat edin, bir etki alanındaysanız, etki alanınız varsayılan olarak 'konum kutusundan' seçilecektir. Bunu "Yerel Bilgisayar" olarak değiştirdiğinizden emin olun. Uygulama havuzu kimliklerini görüntülemek için konumu "Yerel Bilgisayar" olarak değiştirin.


3
Windows Server 2008 R2'de ("Yerel Bilgisayar \ Kişisel" içindeki sertifika için "XXX" Tam Güven olarak) nasıl yapılandırılır? run / mmc / file / ek bileşen / sertifika ekle ve ??? Teşekkürler
Cobaia

7
MMC Sertifikalarınız Yerel Bilgisayar \ Kişisel'e açıldığında, sertifikaları görüntülemek için "sertifika" üzerine tıklayın. (not: aşağıda, sertifikanın zaten içe aktarılmış olduğu varsayılmaktadır, eğer değilse, o zaman önce sertifikayı içe aktarın) Tam denetim vermek istediğiniz sertifikaya sağ tıklayın. Bağlam menüsünde, "Tüm Görevler" e tıklayın, ardından alt menüde "Özel Anahtarları Yönet" e tıklayın. Oradan, sertifika için özel anahtara 'okuma' erişimine sahip olmasını istediğiniz kullanıcıları ekleyebilirsiniz.
thames

5
"Konumdan" kutusunda yerel bilgisayarın seçildiğinden emin olun. Bu beni bir süre şaşırttı. Etki alanı varsayılan olarak seçildi, bu nedenle ben konumu yerel bilgisayara değiştirene kadar uygulama havuzu kimliği kullanıcısını bulamadı
Phil Hale

3
AWS'nin Windows 2012 R2 EC2 IIS_IUSRS
VM'lerinde

4
Bunu powershell ile nasıl yapacağınıza dair bir fikriniz var mı?
sonjz

43

MMC, Sertifikalar, Sertifika Seç, sağ tıklama, tüm görevler, "Özel Anahtarları Yönetme" aracılığıyla izinlerin verilmesi hakkında not

Özel Anahtarları Yönetme yalnızca Kişisel için menü listesindedir ... Bu nedenle, sertifikanızı Güvenilir Kişiler vb. İçine koyarsanız şansınız kalmaz.

Bunun bizim için işe yarayan bir yolunu bulduk. Sertifikayı Kişisel'e sürükleyip bırakın, izinleri vermek için Özel Anahtarları Yönet işlemini yapın. Nesne türü yerleşikleri kullanmayı ve etki alanını değil yerel makineyi kullanmayı unutmayın. DefaultAppPool kullanıcısına haklar verdik ve bunu bıraktık.

İşiniz bittiğinde, sertifikayı orijinal olarak sahip olduğunuz yere sürükleyip bırakın. Presto.


evet bu iyi çalışıyor. Aşağıdaki gönderide bir cevapta bahsetmiştim ancak kabul edilen cevap çok daha uzun olmasına ve bir WCF dosyasının indirilmesini gerektirmesine rağmen başka bir cevap kabul edildi. stackoverflow.com/questions/10580326/…
thames

2
win2003 sunucusu için herhangi bir çözüm? Windows 7 gibi bir seçenek olarak Özel Anahtarları Yönet'e sahip değil
sonjz

1
@sonjz - bu tekneye bir göz atın , komut satırını kullanarak bahsederwinhttpcertcfg
mlhDev

Kişisel dışında herhangi bir şey için sertifikalar için özel anahtarlara ihtiyacınız varsa, büyük olasılıkla yanlış bir şey yapıyorsunuzdur ... Diğer tüm konumlar güvendiğiniz diğer / harici varlıklar içindir. Onların özel anahtarlarına sahip olmamalısınız. Açık anahtarları (sertifikaları) yeterli olmalıdır. Hatta onların özel anahtarlarına sahipseniz onlara güvenmemelisiniz diyebilirim.
Martin

15

IIS'de .pfx dosyasından bir sertifika yüklemeye çalışıyorsanız, çözüm, .pfx dosyasında bu seçeneği etkinleştirmek kadar basit olabilir Application Pool.

Uygulama Havuzuna sağ tıklayın ve seçin Advanced Settings.

Ardından etkinleştirin Load User Profile


görüntü açıklamasını buraya girin


1
Bu neden bir fark yaratır?
MichaelD

3
Pencerelerin kablolanma şekli bu olmalı. Belki profili bir kullanıcı profiline geçici olarak yüklüyor, bu yüzden bu seçeneğe ihtiyacı var. IIS'nin erişebildiği bir dosyadan yükleme yaparken bunun gerekli olmasının garip olduğunu kabul ediyorum.
Simon_Weaver

Bu, PDF'ler için dijital imzalar oluştururken bana yardımcı oldu.
Fred Wilson

7

Birisinin sorduğu Powershell'de bunu nasıl yapacağımı buldum:

$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

6

Benim için bu, sertifikayı "Özel anahtarın dışa aktarılmasına izin ver" işaretli olarak yeniden içe aktarmaktan başka bir şey değildi.

Sanırım gerekli, ancak bu sertifikaya erişen üçüncü taraf bir uygulama olduğu için beni endişelendiriyor.


teşekkür ederim bu şekilde yaptım X509Certificate2 cert = new X509Certificate2 (certBytes, parola, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
Juan Lozoya


0

Yukarıdakilere katılmama rağmen birçok girişimden sonra bu noktaya geldim. 1- Mağazadan sertifikaya erişmek istiyorsanız bunu örnek olarak yapabilirsiniz 2- Sertifikayı üretmek ve bir yoldan kullanmak çok daha kolay ve temizdir

Asp.net Çekirdek 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;
            }
        }

    }
}

VEYA 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")
        );

0

Sertifikalar Panelinde, bazı sertifikalara sağ tıklayın -> Tüm görevler -> Özel anahtarı yönet -> Tam kontrole sahip IIS_IUSRS Kullanıcısı Ekle

Benim durumumda, diğer cevaplarda olduğu gibi "Özel anahtarın dışa aktarılmasına izin ver" seçeneği işaretli olarak sertifikamı yüklememe gerek yoktu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.