SSL握手成功后如何获取peer的QSslCertificate
Posted
技术标签:
【中文标题】SSL握手成功后如何获取peer的QSslCertificate【英文标题】:How to obtain peer's QSslCertificate after successful SSL handshake 【发布时间】:2015-03-02 15:49:10 【问题描述】:当使用 Qt 进行 HTTPS 请求时,我尝试在 SSL 握手后获取对等方的证书,以便跟踪证书的未来变化。
QNetworkAccessManager nam;
nam.get(QNetworkRequest(QUrl("https://google.com/"))); // example URL
QObject::connect(&nam, &QNetworkAccessManager::encrypted, [](QNetworkReply *reply)
qDebug() << reply->sslConfiguration().peerCertificate();
);
根据documentation of QNetworkAccessManager::encrypted
,上面的代码应该可以访问服务器的证书:
当 SSL/TLS 会话成功完成初始握手时会发出此信号。此时,尚未传输任何用户数据。该信号可用于对证书链执行额外检查,例如在网站证书发生更改时通知用户。如果回复不符合预期标准,则应通过连接到此信号的插槽调用 QNetworkReply::abort() 来中止它。可以使用 QNetworkReply::sslConfiguration() 方法检查正在使用的 SSL 配置。
另外,来自documentation of QSslConfiguration::peerCertificate()
:
因为对等证书是在握手阶段设置的,所以从连接到 QSslSocket::sslErrors() 信号、QNetworkReply::sslErrors() 信号或 QSslSocket::encrypted 的插槽访问对等证书是安全的() 信号。
但是,证书始终为空。上述代码的调试输出(进入应用的事件循环后)为:
QSslCertificate( "" , "" , "1B2M2Y8AsgTpgAmY7PhCfg==" , () , () , QMap() , QDateTime(" Qt::LocalTime") , QDateTime(" Qt::LocalTime") )
另一方面,如果遇到 SSL 错误,并且如果我连接到 sslErrors
,我确实会获得证书。例如,对于 Ubuntu / Apache 下的默认证书,由于证书中缺少主机名而未被 Qt 接受,我得到 "https://localhost"
以下内容:
QSslCertificate( "3" , "95:b0:93:f2:16:bb:22:cb" , "cXB6WctE7oZsrvZLU2BWUw==" , () , () , QMap() , QDateTime("2014-07-10 23:04:06.000 UTC Qt::UTC") , QDateTime("2024-07-07 23:04:06.000 UTC Qt::UTC") )
SSL 握手成功后如何获取证书?
我使用 QNetworkAccessManager 的信号以及 QNetworkReply 的信号进行了测试;结果是一样的。
MCVE 可以在https://bitbucket.org/leemes/ssltest找到,随意克隆和摆弄:
git clone https://bitbucket.org/leemes/ssltest.git
我使用 Qt 5.4.0 和 Qt 5.3.1 进行了测试;结果是一样的。
【问题讨论】:
【参考方案1】:这是 Qt 5.4.0 之前的一个错误。它已在 Qt 5.4.1 中修复。
https://bugreports.qt.io/browse/QTBUG-40401
【讨论】:
以上是关于SSL握手成功后如何获取peer的QSslCertificate的主要内容,如果未能解决你的问题,请参考以下文章
HTTPS|SSL笔记-SSL双向认证成功握手过程(含wireshark分析)
Android Studio的安装及"SSL peer shut down incorrectly"问题
当 curl 成功时,Java HTTPS 客户端失败 SSL 握手
javax.net.ssl.SSLHandshakeException:握手期间远程主机关闭连接
已成功与服务器建立连接,但是在登录前的握手期间发生错误。 (provider: SSL Provider, error: 0 - 等待的