2017-10-08 241 views
0

我已經使用自簽名證書(後接Httplistener with https support中的建議)設置了一個測試C#Https Listener。支持Https的Localhost HttpListener - 在一段時間後停止工作

服務(在本地系統下作爲windows服務運行)和最初(啓動後)運行良好。 後的時間(〜1.5小時)在一定期限呼籲HTTPS端點停止與邊緣/ IE抱怨工作:

無法安全地連接到此頁面 這可能是因爲該網站使用了過時的或不安全TLS安全設置。如果這種情況繼續發生,請嘗試聯繫該網站的所有者。

鉻抱怨如下:

這個網站無法達成 連接被重置。 ERR_CONNECTION_RESET

發生這種情況時,檢查證書存儲庫會顯示證書(在Root和My商店中)仍然存在。

檢查

netsh的HTTP顯示的sslcert

還示出了證書到端口的註冊是仍然存在。

重新啓動應用程序(重新創建,重新安裝並將證書重新綁定到C#http偵聽器所偵聽的端口)會有所幫助,但直到下一次可能發生的打嗝(〜1.5 ..2小時?)。

我知道監聽線程仍然活着,因爲不安全端口上的請求仍然有效。

有事在此期間,我想不出什麼...

代碼:

所有與生成一個自簽名證書的開始:

 // create DN for subject and issuer 
     var dn = new CX500DistinguishedName(); 
     dn.Encode("CN=localhost"); 

     // create a new private key for the certificate 
     var privateKey = new CX509PrivateKey 
     { 
      ProviderName = "Microsoft Base Cryptographic Provider v1.0", 
      MachineContext = false, 
      Length = 2048, 
      KeySpec = X509KeySpec.XCN_AT_SIGNATURE, 
      KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_SIGNING_FLAG, 
      FriendlyName = "Application Testing Key", 
      ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_FLAG 
     }; 
     privateKey.Create(); 

     var hashobj = new CObjectId(); 
     hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID, 
      ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, 
      AlgorithmFlags.AlgorithmFlagsNone, "SHA256"); 

     // Create the self signing request 
     var certificateRequest = new CX509CertificateRequestCertificate(); 
     certificateRequest.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextUser, privateKey, String.Empty); 
     certificateRequest.Subject = dn; 
     certificateRequest.Issuer = dn; // the issuer and the subject are the same 
     certificateRequest.NotBefore = DateTime.UtcNow.AddDays(-1); 
     certificateRequest.NotAfter = DateTime.UtcNow.AddYears(10); 
     certificateRequest.HashAlgorithm = hashobj; 

     // Set up the Subject Alternative Names extension. 
     var nameslist = new CAlternativeNames(); 
     var alternativeName = new CAlternativeName(); 
     alternativeName.InitializeFromString(AlternativeNameType.XCN_CERT_ALT_NAME_DNS_NAME, "localhost"); 
     nameslist.Add(alternativeName); 
     var subjectAlternativeNamesExtension = new CX509ExtensionAlternativeNames(); 
     subjectAlternativeNamesExtension.InitializeEncode(nameslist); 
     certificateRequest.X509Extensions.Add((CX509Extension)subjectAlternativeNamesExtension); 

     var skiExtension = new CX509ExtensionSubjectKeyIdentifier(); 
     skiExtension.InitializeEncode(EncodingType.XCN_CRYPT_STRING_BASE64, Convert.ToBase64String(StringToByteArray(certSKI))); 
     certificateRequest.X509Extensions.Add((CX509Extension)skiExtension); 

     certificateRequest.Encode(); 

     // Do the final enrollment process 
     var enroll = new CX509Enrollment(); 
     enroll.InitializeFromRequest(certificateRequest); // load the certificate 
     enroll.CertificateFriendlyName = "Application Testing Cert"; 
     var csr = enroll.CreateRequest(); // Output the request in base64 
     var pwd = Guid.NewGuid().ToString(); 
     enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate, csr, EncodingType.XCN_CRYPT_STRING_BASE64, pwd); // and install it back as the response 
     var base64encoded = enroll.CreatePFX(pwd, PFXExportOptions.PFXExportChainWithRoot); 

     // instantiate the target class with the PKCS#12 data 
     return new X509Certificate2(Convert.FromBase64String(base64encoded), pwd); 

接着向localhost Root和Private store添加新生成的證書:

InstallCertificateToCertStore(cert, new X509Store(StoreName.Root, StoreLocation.LocalMachine)); 
InstallCertificateToCertStore(cert, new X509Store(StoreName.My, StoreLocation.LocalMachine)); 

其次是註冊一個新創建並安裝證書上的HTTP監聽器監聽的端口:

netsh.exe http add sslcert ipport=0.0.0.0:{port} certhash={certThumbprint} appid={appid_guid} 
+0

一些似乎喜歡它的原因可以是進一步廣泛的搜索後我不堅持私鑰:https://support.microsoft.com/en-us/help/950090/installing-a-pfx-file-using-x509certificate-from-a-standard--net-appli測試現在。 –

回答

0

我遇到的問題如下:

當您創建一個自簽名的證書。 NET構建X509Certificate(2)的實例。

如果不指定

X509KeyStorageFlags.PersistKeySet

標誌,則對應於您的證書私鑰將最終被垃圾收集除去到您的證書的所有引用後,去我們的範圍(因此問題不是立即複製,而是經過一段時間)。

要堅持證書的私鑰,您需要指定如上所述的標誌。

這是微軟這裏提到: https://support.microsoft.com/en-us/help/950090/installing-a-pfx-file-using-x509certificate-from-a-standard--net-appli

自簽名證書創建中的最後工作的代碼如下:

 // create DN for subject and issuer 
     var dn = new CX500DistinguishedName(); 
     dn.Encode("CN=localhost"); 

     // create a new private key for the certificate 
     var privateKey = new CX509PrivateKey 
     { 
      ProviderName = "Microsoft Base Cryptographic Provider v1.0", 
      MachineContext = true, 
      Length = 2048, 
      KeySpec = X509KeySpec.XCN_AT_SIGNATURE, 
      KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES, 
      FriendlyName = "App Testing Key", 
      ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_FLAG 
     }; 
     privateKey.Create(); 

     var hashobj = new CObjectId(); 
     hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID, 
      ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, 
      AlgorithmFlags.AlgorithmFlagsNone, "SHA256"); 

     // Create the self signing request 
     // also see: https://security.stackexchange.com/a/103362 
     var certificateRequest = new CX509CertificateRequestCertificate(); 
     certificateRequest.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextMachine, privateKey, String.Empty); 
     certificateRequest.Subject = dn; 
     certificateRequest.Issuer = dn; // the issuer and the subject are the same 
     certificateRequest.NotBefore = DateTime.UtcNow.AddDays(-1); 
     certificateRequest.NotAfter = DateTime.UtcNow.AddYears(10); 
     certificateRequest.HashAlgorithm = hashobj; 

     // Set up the Subject Alternative Names extension. 
     var nameslist = new CAlternativeNames(); 
     var alternativeName = new CAlternativeName(); 
     alternativeName.InitializeFromString(AlternativeNameType.XCN_CERT_ALT_NAME_DNS_NAME, "localhost"); 
     nameslist.Add(alternativeName); 
     var subjectAlternativeNamesExtension = new CX509ExtensionAlternativeNames(); 
     subjectAlternativeNamesExtension.InitializeEncode(nameslist); 
     certificateRequest.X509Extensions.Add((CX509Extension)subjectAlternativeNamesExtension); 

     var skiExtension = new CX509ExtensionSubjectKeyIdentifier(); 
     skiExtension.InitializeEncode(EncodingType.XCN_CRYPT_STRING_BASE64, Convert.ToBase64String(StringToByteArray(certSKI))); 
     certificateRequest.X509Extensions.Add((CX509Extension)skiExtension); 

     certificateRequest.Encode(); 

     // Do the final enrollment process 
     var enroll = new CX509Enrollment(); 
     enroll.InitializeFromRequest(certificateRequest); // load the certificate 
     enroll.CertificateFriendlyName = "App Testing Cert"; 
     var csr = enroll.CreateRequest(); // Output the request in base64 
     var pwd = Guid.NewGuid().ToString(); 
     enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate, csr, EncodingType.XCN_CRYPT_STRING_BASE64, pwd); // and install it back as the response 
     var base64encoded = enroll.CreatePFX(pwd, PFXExportOptions.PFXExportChainWithRoot); 

     // instantiate the target class with the PKCS#12 data 
     return new X509Certificate2(Convert.FromBase64String(base64encoded), pwd, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);