首页 文章

hotmail.com上的QT ssl错误:无法找到本地查找证书的颁发者证书

提问于
浏览
6

当我使用QtWebkit(内部使用QSslSocket)连接到www.hotmail.com时,登录后出现以下ssl错误:

  • 找不到本地查找证书的颁发者证书

  • 为此目的不信任根CA证书

  • 无法验证证书 .

登录前我可以在mail.yahoo.com上遇到相同的错误 . 我发现与这两个服务器的安全连接会触发ssl错误:

QT附带了一个名为securesocketclient的小型ssl演示程序 . 如果我使用这个小客户端连接到上述两个服务器的端口443,我可能会产生相同的错误 . 我99%肯定这是QT的一个错误,因为我们在许多开发系统上产生了这个问题 . 它会影响linux,mac和windows QT . 它影响QT 4.7.4一直到QT 4.8.4(没有尝试早期版本) . 使用openssl 0.9.8复制该错误 .

有些人可能错误地声称使用带有预编译QT二进制文件的openssl 1.0.0修复了该错误 . 这是错误的,因为预编译的QT二进制文件是使用openssl 0.9.8头文件编译的 . Openssl 0.9.8与openssl 1.0.0不是二进制兼容的 . 如果使用一个版本的openssl编译QT但使用另一个版本的openssl二进制文件,一些结构成员将被误解 . 我做了很多步骤和跟踪到QT和openssl源代码来得出这个结论 .

由于hotmail和yahoo电子邮件是非常受欢迎的网站,我认为这个bug在QT的安全性方面是一个严重的错误 . 我已经将它报告给了QT bug系统(https://bugreports.qt.io/browse/QTBUG-23625),我怀疑digia是否会根据我过去的经验得到它 .

请随时分享您对如何解决此错误的看法 . 我知道如何调用ignoreSslErrors并假装没有问题 . 但这并不是打算如何使用openssl .


Some updates from further investigation on this issue.

https://gfx8.hotmail.com的证书路径是:

  • 根CA:Versign Class 3公共主要证书颁发机构 - G5

  • 中间CA:Versign Class 3扩展验证SSL SGC CA.

  • 服务器证书:gfx-ecn.hotmail.com

根CA确实位于Windows证书存储区中,并在启动时正确加载 . 我想也许不知何故QT没有获得中间证书 . 我使用openssl命令行程序运行测试,如下所示:

openssl s_client -showcerts -connect gfx8.hotmail.com:443

输出在这里:

CONNECTED(000001AC)depth = 0 1.3.6.1.4.1.311.60.2.1.3 = US,1.3.6.1.4.1.311.60.2.1.2 = Washington,bu sinessCategory = Private Organization,serialNumber = 600413485,C = US, postalC ode = 98052,ST = Washington,L = Redmond,street = 1 Microsoft Way,O = Microso ft Corporation,OU = Windows Azure CDN,CN = gfx-ecn.hotmail.com验证错误:num = 20:无法获取本地发行人证书验证返回:1深度= 0 1.3.6.1.4.1.311.60.2.1.3 = US,1.3.6.1.4.1.311.60.2.1.2 =华盛顿,bu sinessCategory =私人组织,serialNumber = 600413485,C = US,postalC ode = 98052,ST = Washington,L = Redmond,street = 1 Microsoft Way,O = Microso ft Corporation,OU = Windows Azure CDN,CN = gfx-ecn.hotmail.com验证错误:num = 27:证书不信任验证返回:1深度= 0 1.3.6.1.4.1.311.60.2.1.3 =美国,1.3.6.1.4.1.311.60.2.1.2 =华盛顿,bu sinessCategory =私人组织,serialNumber = 600413485,C = US ,postalC ode = 98052,ST = Washington,L = Redmond,street = 1 Microsoft W ay,O = Microso ft Corporation,OU = Windows Azure CDN,CN = gfx-ecn.hotmail.com验证错误:num = 21:无法验证第一个证书验证返回:1证书链0 s:/1.3.6.1 . 4.1.311.60.2.1.3 = US / 1.3.6.1.4.1.311.60.2.1.2 = Washington / businessCategory = Private Organization / serialNumber = 600413485 / C = US / postalCode = 98052 / ST = Washington / L = Redmond / street = 1 Microsoft Way / O = Microsoft Corporation / OU = Windows Azure CDN / CN = gfx-ecn.hotmail.com i:/ C = US / O = VeriSign,Inc. / OU = VeriSign Trust Network / OU =使用条款在https://www.verisign.com/rpa(c)中06 / CN = VeriSign公司3类扩展确认SSL SGC CA ----- BEGIN CERTIFICATE ----- MIIG0DCCBbigAwIBAgIQfRbsuTLd2GrmU38TPnVOCTANBgkqhkiG9w0BAQUFADCB vjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug YXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykwNjE4MDYGA1UEAxMvVmVyaVNpZ24gQ2xhc3MgMyBFeHRlbmRlZCBWYWxpZGF0aW9uIFNTTCBTR0MgQ0Ew HhcNMTIxMTA3MDAwMDAwWhcNMTQxMTA4MjM1OTU5WjCCAR0xEzARBgsrBgEEAYI3 PAIBAxMCVVMxGzAZBgsrBgEEAYI3PAIBAhMKV2FzaGluZ3RvbjEdMBsGA1UEDxMU UHJpdmF0ZSBPcmdhbml6YXRpb24xEjAQBgNVBAUTCTYwMDQxMzQ4NTELMAkGA1UE BhMCVVMxDjAMBgNVBBEUBTk4MDUyMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD VQQHFAdSZWRtb25kMRgwFgYDVQQJFA8xIE1pY3Jvc29mdCBXYXkxHjAcBgNVBAoU FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEaMBgGA1UECxQRV2luZG93cyBBenVyZSBD RE4xHDAaBgNVBAMUE2dmeC1lY24uaG90bWFpbC5jb20wggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQC jRmBRv2iw1N2LirFdhgqmZ3G BBc8gAn50O6TT1u zNqrjicf3KJ BDHSGcnkysvWovwnUhDhMzAWf521iYi2lFZqC3txewGvjrKM0Gqz DhHrF bzvNjyrIION89354cFxU1eK2okegYHkWIuyPHyCN6PFGK52OlkBixb34xv WvAZfjSu /小时˚FlkedFZvJdd6KS4e8N / TGJ / dndfmReaKSiNFWBFbwhkndLdXU3p ZnVLCysETMuUoIsDIPcgDfji1XkoKLsri9WijVhjNH1MFf / T6 / g4PpWqZGl4si3t yQ0rdefDGfgX8lvq63aXnaap4SbjTYLviFRle / PMkXV7AgMBAAGjggJmMIICYjCB 0AYDVR0RBIHIMIHFghBnZngxLmhvdG1haWwuY29tghBnZngyLmhvdG1haWwuY29t ghBnZngzLmhvdG1haWwuY29tg hBnZng0LmhvdG1haWwuY29tghBnZng1LmhvdG1h aWwuY29tghBnZng2LmhvdG1haWwuY29tghBnZng3LmhvdG1haWwuY29tghBnZng4 LmhvdG1haWwuY29tghRncmFwaGljcy5ob3RtYWlsLmNvbYIIYS5nZngubXOCE2dm eC1lY24uaG90bWFpbC5jb20wCQYDVR0TBAIwADAdBgNVHQ4EFgQUH0b2ApITW9WB / LA OAZ 2ZnW / dwwDgYDVR0PAQH / BAQDAgWgMD4GA1UdHwQ3MDUwM6AxoC GLWh0 dHA6Ly9FVkludGwtY3JsLnZlcmlzaWduLmNvbS9FVkludGwyMDA2LmNybDBEBgNV HSAEPTA7MDkGC2CGSAGG EUBBxcGMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3 LnZlcmlzaWduLmNvbS9jcHMwNAYDVR0lBC0wKwYIKwYBBQUHAwEGCCsGAQUFBwMC BglghkgBhvhCBAEGCisGAQQBgjcKAwMwHwYDVR0jBBgwFoAUTkPIHXbvN1N6T / JY b5TzOOLVvd8wdgYIKwYBBQUHAQEEajBoMCsGCCsGAQUFBzABhh9odHRwOi8vRVZJ bnRsLW9jc3AudmVyaXNpZ24uY29tMDkGCCsGAQUFBzAChi1odHRwOi8vRVZJbnRs LWFpYS52ZXJpc2lnbi5jb20vRVZJbnRsMjAwNi5jZXIwDQYJKoZIhvcNAQEFBQAD ggEBAFdVsrzkxJ6aRnaGIO1hbCDlekEMCT6OTlZXckzZeaIrNfSFLXHe89pWkRr1 AKz43nnM0pLxVuEHRE9pMZH6Om7SjqU5BR1qd6xp ZJhuJA2I2319PCSbKCpv67X 82J8 / JKjH8e4fpOzb70dKUlNNr7x0aIMYuCq6unXXZQ5u83Uny42jcIQWLOlZRKC dYSqW3JalTYVZNvdEoQVuUEJJLcY1qMVJ9NFtdnrzrmcpK 52 nZQXbCkM7W8Vl1 WM / dbOnqsu0 SIPZ4Q2wIAnT1azmBvxZ2ULvzW98HIAn4 / RdPuimnox8T9R2yrv1 xd5P6oAZWvmnX6e461m6HohhhDw = ----- END CERTIFICATE -----服务器证书主题= / 1.3.6.1.4.1.311.60.2.1.3 = US / 1.3.6.1.4.1.311.60.2.1 . 2 = Washington / businessCategory = Private Organization / serialNumber = 600413485 / C = US / postalCode = 98052 / ST = Washington / L = Redmond / street = 1 Microsoft Way / O = Microsoft Corporation / OU = Windows Azure CDN / CN = gfx- ecn.hotmail.com issuer = / C = US / O = VeriSign,Inc. / OU = VeriSign Trust Network / OU =使用条款:https://www.verisign.com/rpa(c)06 / CN = VeriSign 3级扩展验证SSL SGC CA无客户端证书CA名称已发送SSL握手已读取1933字节并写入480字节新增,TLSv1 / SSLv3,密码为AES256-SHA服务器公钥为2048位安全重新协商IS支持压缩:无扩展:无SSL-Session:协议:SSLv3密码:AES256-SHA会话ID:3CC559C15AF17B09346C371A1CB292DF77C272A37FDC4DF69EEE0EE9CC067B5C Session-ID-ctx:主密钥:F626E23FDCC89B1329FD4F5D1ED5A9 40F0CB14A1C377BFDB6ABA6238B91F9C11390EC16FD117C090B3171FBEE762B792 Key-Arg:无PSK标识:无PSK标识提示:无开始时间:1355423684超时:7200(秒)验证返回码:21(无法验证第一个证书)

从openssl的输出中,我们可以看到openssl程序产生类似的错误(这使得它看起来更像是一个openssl bug?) . 我们还注意到hotmail服务器仅返回服务器证书,但不返回中间证书 . 这可能是导致错误的原因 . 我和其他https服务器尝试了相同的ssl命令 . 它们还返回服务器证书和中间证书 . 我测试过的一些银行网站甚至将整个证书链一直返回到根CA.所以,问题是,如果没有返回中间证书,我应该从何处和在哪里获得它? IE和Chrome等其他浏览器如何处理这个问题?


More findings here.

实际上,我提到的两个服务器都用于下载hotmail和yahoo邮件的页内组件 . 雅虎邮件主登录页面本身确实返回完整的证书链 . 当其他浏览器访问主页面时,它将在本地存储中间证书以供以后使用 . 但是,QTWebkit不会自动缓存中间证书,从而导致问题 . 如果我直接使用firefox的新副本访问服务器https://gfx8.hotmail.com,我会收到同样的错误 . 但是,如果我访问首先https:/www.hotmail.com然后登录到hotmail,虽然登录后从gfx8服务器下载了一些组件,但没有错误 . 我发现QTWebkit既没有从系统证书存储加载中间证书,也没有将中间证书添加到系统证书存储中 . 它没有't cache intermediate certificates internally in memory either. That will cause problem for some servers which doesn' t返回完整的证书链 .

我确实尝试将中间证书保存到PEM文件并在启动我的应用程序时加载它 . 它在Windows和Linux上运行良好 . 但不知何故,它对Mac没有影响 . 不知道为什么 .

1 回答

  • 3

    为了支持应用程序中的安全连接,没有ignorig ssl错误,您必须拥有您正在加载的站点正在访问的所有域的根证书,例如,如果它访问CDN(在网络面板中你的浏览器),也可以获得服务器的证书(你可以从chrome下载它们,例如,通过查看当前站点的证书,并获得整个链,但单独下载它们) . 将所有这些证书存储在一个单独的文件夹中后,在应用程序初始化后的某处添加此代码,它将在开头加载所有这些代码,因此QT可以访问它们:

    import os
    
    from PySide.QtNetwork import QSsl, QSslConfiguration, QSslCertificate
    from PySide.QtCore import QFile, QIODevice
    
    
    def load_certs(cert_path):
        # cert_path is a string "/path/to/cert/files"
        ssl_config = QSslConfiguration.defaultConfiguration()
        ssl_config.setProtocol(QSsl.SecureProtocols)
    
        certs = ssl_config.caCertificates()
    
        for cert_filename in os.listdir(cert_path):
            if os.path.splitext(cert_filename)[1] in ('.cer', '.crt', '.pem'):
                cert_filepath = os.path.join(cert_path, cert_filename)
                cert_file = QFile(cert_filepath)
                cert_file.open(QIODevice.ReadOnly)
                cert = QSslCertificate(cert_file)
                certs.append(cert)
    
        ssl_config.setCaCertificates(certs)
        QSslConfiguration.setDefaultConfiguration(ssl_config)
    

    现在,当一个站点需要证书验证时,它在Debian系统上赢得了TLS实现,在这些情况下,当您没有有效证书时,您将遇到诸如页面永不加载或类似错误之类的问题 . 在这些情况下,您必须强制使用SSLv3来处理这些页面,以使它们正常工作 . 您可以通过将自定义虚拟功能绑定到QNetworkAccessManager的createRequest,并覆盖每个请求的ssl协议来实现 . 这样你就不是最好的主意了,只针对那些有问题的人:

    class Browser(object):
    
        def __init__(self):
            self.network_manager = QNetworkAccessManager()
            self.network_manager.createRequest = self._create_request
            self.web_page = QWebPage()
            self.web_page.setNetworkAccessManager(self.network_manager)
            self.web_view = QWebView()
            self.web_view.setPage(self.web_page)
            self._override_ssl = None
    
        def _create_request(self, operation, request, data):
            ssl_protocols = {'sslv2': QSsl.SslV2,
                             'sslv3': QSsl.SslV3,
                             'tlsv1': QSsl.TlsV1,
                             'tlsv1sslv3': QSsl.TlsV1SslV3,
                             'unknownprotocol': QSsl.UnknownProtocol,
                             'secureprotocols': QSsl.SecureProtocols}
    
            if self._override_ssl is not None:
                ssl_config = QSslConfiguration.defaultConfiguration()
                ssl_config.setProtocol(ssl_protocols[self._override_ssl])
                request.setSslConfiguration(ssl_config)
    
            reply = QNetworkAccessManager.createRequest(self.network_manager,
                                                        operation,
                                                        request,
                                                        data)
    
            return reply
    
        def override_ssl(self, protocol_id):
            # protocol id is a string like 'sslv3' or 'tlsv1'
            self._override_ssl = protocol_id
    

    好吧,我从内存中输入了大部分代码,请报告是否有问题 .

相关问题