在 ubuntu 24.04 系统开发内嵌 webkit2gtk-4.1 的应用,打开部分 HTTPS 网页报错“Unacceptable TLS certificate”, 如下图:
但是相同的页面使用 FireFox/Safari/Chrome/IE/Edge 等主流浏览器打开都是正常显示的。
调试代码,发现是 WebKitWebView 的 on_load_failed_with_tls_errors 回调函数返回了错误 G_TLS_CERTIFICATE_GENERIC_ERROR(64),如下图:
于是安装 Gnome 官方的浏览器 Epiphany 进行测试,该浏览器底层也是调用 WebKit2GTK,在 ubuntu 24.04 系统,可以执行如下命令进行安装:
1 |
$ sudo apt install epiphany-browser |
打开相同的页面,同样报错,显示服务器不可信。
由于 WebKit2GTK 底层的 TLS 通信调用库调用的是 GnuTLS 。于是尝试通过命令行对 TLS 证书认证过程进行验证,执行如下命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ sudo apt install gnutls-bin $ gnutls-cli www.xxxx.com Processed 146 CA certificate(s). Resolving 'www.xxxx.com:443'... Connecting to 'xxx.xxx.xxx.xxx:443'... ........................................................................ ........................................................................ - Certificate[4] info: - subject `CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE', issuer `CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE', serial xxxxxx, RSA key 2048 bits, signed using RSA-SHA1 (broken!), activated `xxxx-xx-xx xx:xx:xx UTC', expires `xxxx-xx-xx xx:xx:xx UTC', pin-sha256="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - Status: The certificate is NOT trusted. The certificate chain violates the signer's constraints. *** PKI verification of server certificate failed... *** Fatal error: Error in the certificate. |
可以看到,网站的根证书无法通过 GnuTLS 的验证,原因在于网站的证书链中的根证书使用的 RSA-SHA1 签名,该类型签名存在 “弱哈希算法签名的SSL证书(CVE-2004-2761)漏洞” 进而被 GnuTLS 拒绝。
针对此问题的更详细的描述参考 GnuTLS 文档 8.2 Disabling algorithms and protocols 。
针对此问题的解决方法:
-
联系网站,更新证书,重新以 RSA-SHA256 签发证书。由于是公司内部网址,因此联系网络更新即可;
-
应用内嵌网站证书,通过 webkit_web_context_allow_tls_certificate_for_host 要求 webkit 通过提供的证书进行网站验证。此种情况适用于 APP 内嵌自己网站页面的情况,同样适用于自签名证书的情况;
-
如果纯粹测试,可以在加载页面之前调用
123456789// 网站证书存在问题,此处仅为测试场景下,临时关闭TLS证书验证auto context = webkit_web_view_get_context(WEBKIT_WEB_VIEW(web_view_));// 低版本 4.0webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_IGNORE);// 高版本 4.1auto manager = webkit_web_context_get_website_data_manager(context);webkit_website_data_manager_set_tls_errors_policy(manager, WEBKIT_TLS_ERRORS_POLICY_IGNORE);要求 webkit 无视证书错误。此方法生产环境不可取,非常不安全,仅可用于内部测试;
-
此方案目前测试已经不可用:
调用 gnutls_sign_set_secure_for_certs API 许可部分不安全的证书签名算法123456// pkg_check_modules(GnuTLS REQUIRED IMPORTED_TARGET gnutls>=3.7.3)// target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GnuTLS)// #include <gnutls/gnutls.h>gnutls_sign_set_secure_for_certs(GNUTLS_SIGN_RSA_SHA1, 1);相对来说,联系不上网站的情况下,又需要在保证安全的前提下,尽量兼容网站,推荐此种方式; -
自行接管证书验证过程,实现比较复杂,极其容易产生安全漏洞,不建议;