다음과 같이 실행 중이며 Google 및 스택 오버플로에 대한 여러 가지 방법을 다 써 버린 것처럼 느껴본 후에 필자는 자신의 질문을하기로했습니다. .생성 된 인증서를 저장소에 추가하고 IIS 사이트 바인딩을 업데이트하십시오.
나는 이미 소유하고 소유하고있는 CA 인증서를 기반으로하는 개인 인증서 (BouncyCastle 사용)를 생성하려고합니다. 인증서를 생성 한 후 'My'저장소에 저장 한 다음 IIS 웹 사이트의 SSL 바인딩을 업데이트하여이 새 인증서를 사용하려고합니다.
IIS 웹 사이트 (ServerManager
사용)의 업데이트가 예외를 발생시키지 않고 IIS 관리자 콘솔로 이동하면 웹 사이트의 바인딩에 SSL 인증서가 선택되어 있음을 알 수 있습니다. 나는 (개인 키) 내 생성 된 인증서를 내 보낸 테스트로
A specified logon session does not exist. It may already have been terminated. (Exception from HRESULT: 0x80070520)
과 : 내가 만든 인증서를 선택하려고 할 때 나는 다음과 같은 오류 메시지가 (실행 가능한 옵션으로 고급을 보여줍니다) 마법사를 통해 다시 설치 한 다음 IIS 관리자를 통해 바인딩을 설정하는 작업을 다시 시도했습니다.
이 동작으로 인해 저장소에 인증서를 생성하거나 추가하는 방법에 문제가 있다고 생각했습니다. 나는 누군가가 내가 가질 수있는 이슈에 대해 약간의 아이디어를 얻길 바랬다. 인증서 만들기, 저장소에 추가 및 프로그래밍 방식으로 웹 사이트 바인딩을 업데이트하는 데 사용되는 관련 기능은 다음과 같습니다 (믿습니다) :
CA 인증서 개인 키를 생성하는 주요 기능으로, 인증서에 서명하고, 사이트 바인딩 업데이트 :
public static bool GenerateServerCertificate(
X509Certificate2 CACert,
bool addToStore,
DateTime validUntil)
{
try
{
if (CACert.PrivateKey == null)
{
throw new CryptoException("Authority certificate has no private key");
}
var key = DotNetUtilities.GetKeyPair(CACert.PrivateKey).Private;
byte[] certHash = GenerateCertificateBasedOnCAPrivateKey(
addToStore,
key,
validUntil);
using (ServerManager manager = new ServerManager())
{
Site site = manager.Sites.Where(q => q.Name == "My Site").FirstOrDefault();
if (site == null)
{
return false;
}
foreach (Binding binding in site.Bindings)
{
if (binding.Protocol == "https")
{
binding.CertificateHash = certHash;
binding.CertificateStoreName = "MY";
}
}
manager.CommitChanges();
}
}
catch(Exception ex)
{
LOG.Error("Error generating certitifcate", ex);
return false;
}
return true;
}
은 CA 개인 키를 기반으로 인증서를 생성 :
public static byte[] GenerateCertificateBasedOnCAPrivateKey(
bool addToStore,
AsymmetricKeyParameter issuerPrivKey,
DateTime validUntil,
int keyStrength = 2048)
{
string subjectName = $"CN={CertSubjectName}";
// Generating Random Numbers
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom random = new SecureRandom(randomGenerator);
ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerPrivKey, random);
// The Certificate Generator
X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
certificateGenerator.AddExtension(
X509Extensions.ExtendedKeyUsage,
true,
new ExtendedKeyUsage((new List<DerObjectIdentifier> { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1") })));
// Serial Number
BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
certificateGenerator.SetSerialNumber(serialNumber);
// Issuer and Subject Name
X509Name subjectDN = new X509Name(subjectName);
X509Name issuerDN = new X509Name(CACertificateName);
certificateGenerator.SetIssuerDN(issuerDN);
certificateGenerator.SetSubjectDN(subjectDN);
// Valid For
DateTime notBefore = DateTime.UtcNow.Date;
DateTime notAfter = validUntil > notBefore ? validUntil : notBefore.AddYears(1);
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
Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(signatureFactory);
// correcponding private key
PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(subjectKeyPair.Private);
// merge into X509Certificate2
X509Certificate2 x509 = new X509Certificate2(certificate.GetEncoded());
Asn1Sequence seq = (Asn1Sequence)Asn1Object.FromByteArray(info.ParsePrivateKey().GetDerEncoded());
if (seq.Count != 9)
{
throw new PemException("Malformed sequence in RSA private key");
}
RsaPrivateKeyStructure rsa = RsaPrivateKeyStructure.GetInstance(seq);
RsaPrivateCrtKeyParameters rsaparams = new RsaPrivateCrtKeyParameters(
rsa.Modulus,
rsa.PublicExponent,
rsa.PrivateExponent,
rsa.Prime1,
rsa.Prime2,
rsa.Exponent1,
rsa.Exponent2,
rsa.Coefficient);
x509.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
if (addToStore)
{
// Add certificate to the Personal store
AddCertToStore(x509, StoreName.My, StoreLocation.LocalMachine, "Certificate Friendly Name");
}
return x509.GetCertHash();
}
가게에 인증서를 추가 :
private static void AddCertToStore(X509Certificate2 cert, StoreName storeName, StoreLocation storeLocation, string friendlyName)
{
X509Store store = new X509Store(storeName, storeLocation);
try
{
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
if (!string.IsNullOrWhiteSpace(friendlyName)) {
var certs = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, cert.Subject, true);
if (certs.Count > 0)
{
certs[0].FriendlyName = friendlyName;
}
}
}
finally
{
store.Close();
}
}
그냥 마지막 주, 나는 (문제가 무엇인지 명확하지 않는 것) 내가 그 오류에 관해서 여러 사이트에서 본 것과 몇 가지를 시도 :
- 이것은 다른 상자 (개인 개발 컴퓨터)에서 작동하지만 서버 컴퓨터 (Windows Server 2012 R2 실행)에서 이러한 장애를 쳤습니다.
- IIS 도움말 대화 상자에서 컴퓨터가 IIS 실행 중임을 알립니다.
- 유효성이 검증되었습니다. 인증서 및 CertUtil.exe가있는 CA 인증서
- 생성 된 인증서를 확인했으며 CA 인증서에 찾을 수있는 개인 키가 있음
- 인증 된 관리자 (결국 로그인 한 계정까지도)는 CA 인증서와 생성 된 인증서 모두의 개인 키 파일에 액세스 할 수있었습니다.
어떤 아이디어가 내 문제 일 수 있습니까?
업데이트 :
나는 다음을 수행하여 어떤 결과를 얻을 수 있었다 :
이수출 프로그래밍 File.WriteAllBytes(filePath, cert.Export(X509ContentType.Pkcs12, password));
을 수행하여 파일에 내 인증서가 그럼 난이 인증서 가져 오기 다음을 수행하여 상점에 파일을 보냅니다.
var cert = new X509Certificate2(certFilePath, certPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
// My original AddCertToStore function
AddCertToStore(cert, StoreName.My, StoreLocation.LocalMachine, "Friendly Name");
마지막으로, 이전에하던대로 나는 바인딩을 설정
using (ServerManager manager = new ServerManager())
{
Site site = manager.Sites.Where(q => q.Name == "My Site").FirstOrDefault();
if (site == null)
{
return false;
}
foreach (Binding binding in site.Bindings)
{
if (binding.Protocol == "https")
{
binding.CertificateHash = certHash;
binding.CertificateStoreName = "MY";
}
}
manager.CommitChanges();
}
이 방법은 작업을 수행,하지만 난 그런 다음 인증서를 파일로 내 보냅니다 가지고에로드 할 이유는 표시되지 않습니다 X509Certificate2 개체를 만들고 저장소에 추가 한 다음 마지막으로 바인딩을 설정합니다.
비슷한 코드에서 같은 문제가 발생했으며'X509KeyStorageFlags.MachineKeySet'을 추가하면 확실히 문제가 해결됩니다. –