成功进行SSL握手后如何获取对等的QSslCertificate

时间:2015-03-02 15:49:11

标签: c++ qt ssl https qnetworkaccessmanager

使用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的信号;结果是一样的。


可以在https://bitbucket.org/leemes/ssltest 找到MCVE,随意克隆和摆弄:

git clone https://bitbucket.org/leemes/ssltest.git

我使用Qt 5.4.0和Qt 5.3.1进行了测试;结果是一样的。

1 个答案:

答案 0 :(得分:2)

这是Qt中的一个错误,最高可达5.4.0。它已在Qt 5.4.1中修复。

https://bugreports.qt.io/browse/QTBUG-40401