2017-03-14 97 views
1

在Chrome中查看證書詳細信息時,Windows顯示的給定證書的公鑰與Qt在連接到加密信號的插槽中返回的內容不同。QSslCertificate如何獲取Windows中顯示的公共密鑰

auto onEncrypt = [](QNetworkReply* rpl) { 
    auto cert = rpl->sslConfiguration().peerCertificate(); 
    auto publicKey = cert.publicKey(); 

    QString winHexKey = "3082010a0282010100d8..."; // as displayed in cert info of Chrome on Windows for the Public Key 
    auto windowsKey = QByteArray::fromHex(winHexKey.toUtf8()); 
    if (windowsKey == publicKey.toPem()) 
     std::cout << "PEM key matched\n"; 
    else if (windowsKey == publicKey.toDer()) 
     std::cout << "DER key matched\n"; 
    else if (winHexKey == publicKey.toPem().toHex()) 
     std::cout << "Hex PEM key matched\n"; 
    else if (winHexKey == publicKey.toDer().toHex()) 
     std::cout << "Hex DER key matched\n"; 
    else 
     std::cout << "No match!\n"; 
    std::cout << publicKey.toPem().toHex().toStdString() << '\n'; // 902 characters worth starting with 2d2d2d2d2d 
}; 
QNetworkAccessManager mgr; 
QObject::connect(&mgr, &QNetworkAccessManager::encrypted, onEncrypt); 
QNetworkRequest r(QUrl::fromUserInput("https://www.qt.io")); 
mgr.get(r); 

總是導致不匹配。有趣的是,公鑰的十六進制輸出比Windows顯示的要大得多。

如何才能獲取服務器提供的證書的公鑰,並根據證書中存在的內容驗證證書?

回答

0

一個人如何可以得到由服務器

提供的證書的公鑰公鑰是證書部分。證書還將包含散列,這些散列可以對證書內容進行一些基本的完整性檢查。要檢查服務器是否與證書實際匹配,您必須嘗試建立加密通道。服務器或者以與從客戶端觀察到的證書一致的方式引導加密的信道 - 也就是說,服務器與爲其呈現的證書匹配;或者它不 - 這是導致警報的原因。

驗證它是否與證書中存在的內容相對應?

X.509證書還包含散列,可用於完整性檢查。

Chrome解碼PEM/DER/BER時,Chrome顯示的內容與您的代碼所做的內容之間的差異。 DER/BER添加一些額外的元數據來描述字段類型和長度; PEM是底層X.509證書內容的特定編碼。

+0

雖然這並沒有真正回答我的問題。是的,公鑰是證書的一部分,但我需要驗證它以確保它是預期的證書(因此也是真實的服務器),而不僅僅是一些自簽名證書(如果將其添加到信任存儲區)某處。不能使用指紋,因爲如果證書被更新,指紋會發生變化,而公鑰不一定會改變。 – Phoenix

+0

你的問題並不明顯,你知道這一點。如果您期望某個公鑰,擴展您期望簽名的某個值。其他領域如CN應該不會改變。 X.509證書的要點是,您並不在乎服務器的特定密鑰是什麼,而是與證書相匹配的任何密鑰都可以執行,並且您擁有從證書到CA的外部信任鏈到客戶端信任庫來驗證*事實*代替。 – user268396

0

如果您想通過同行驗證發送請求,則無需手動驗證。使用QSslConfiguration並將您的證書文件從Chrome設置爲CA證書。例如:

QSslConfiguration config = QSslConfiguration::defaultConfiguration(); 
// Load certificate from file to QByteArray chromeCertificateByteArray 
QSslCertificate ca = QSslCertificate(chromeCertificateByteArray); 
QList <QSslCertificate> caList; 
caList.append(ca); 
config.setCaCertificates(caList); 

QNetworkRequest request(QUrl::fromUserInput("https://www.qt.io")); 
request.setSslConfiguration(config); 

QNetworkAccessManager networkManager; 
QNetworkReply* reply = networkManager.get(request); 
+0

那麼,只需拿CA鏈,並使該連接的唯一可接受的CA?如果證書更新並且CA決定使用其他中間證書會怎麼樣?或者更改他們的根證書進行簽名?在這種情況下,如果我有這個權利,它會失敗。 – Phoenix