How to add CA certificate to QSslConfiguration
-
First of all, I want apologize for probably stupid question.
I need to download file from a HTTPS server. The problem is that server uses CA certificate (Digicert) that is not recognized by Linux although it works fine in browser. If I run:curl --verbose https://server/file
I get this error:
curl: (60) SSL certificate problem: unable to get local issuer certificate
So I have downloaded CA certificate to cacert.crt file and after providing that certificate to curl, it works and firl is downloaded:
curl --verbose https://server/file --cacert cacert.crt
Now, I want to achieve the same in Qt 6 but so far without any success. I am trying to add CA cert to QSslConfiguration but it does not work:
QByteArray cert = R"(-----BEGIN CERTIFICATE----- MIIGJzCCBQ+gAwIBAgIQAq2BXDbORNVanb6A/36zgjANBgkqhkiG9w0BAQsFADBg MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMR8wHQYDVQQDExZSYXBpZFNTTCBUTFMgUlNBIENBIEcx MB4XDTI0MDYxMDAwMDAwMFoXDTI1MDYwOTIzNTk1OVowGDEWMBQGA1UEAwwNKi5k YWJsaXN0Lm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMgNZkE4 aQbP5npnaycnZY5QwaCFqOC1hEQCs/gqiTba46KunrYeWngf6ObA0QZbAIBZsnIq 1lad/GwicptYJHvNICOy9/vuDHbmD/gMgGzvzhApG0euNYnGMf3OOwvQN2vf7DCk M3GxDTzQqWJaVSkFyFQjjZywT1mhfdL7Q93fCPLdTEwhRAqGQ3y8RKnnducRI8ZG 0ZSydKq9991WClO0WUbnMctMBlRnQW4U55FtQEEgmVS+Waiy8UhyGj3Dj/sSlcgD H66dkYFebkps36e2CJL26UyV8CPBHddQgEDv8GKwhBNS0PFVHad08N/PbpH0nNse Q8T/YOmscq6BsoUCAwEAAaOCAyMwggMfMB8GA1UdIwQYMBaAFAzbbIJJD0pnCrgU 7nrESFKI61Y4MB0GA1UdDgQWBBTUjdJOwkm7oOW9UKg8Ilplh2WoITAlBgNVHREE HjAcgg0qLmRhYmxpc3Qub3JnggtkYWJsaXN0Lm9yZzA+BgNVHSAENzA1MDMGBmeB DAECATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA/ BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY2RwLnJhcGlkc3NsLmNvbS9SYXBpZFNT TFRMU1JTQUNBRzEuY3JsMHYGCCsGAQUFBwEBBGowaDAmBggrBgEFBQcwAYYaaHR0 cDovL3N0YXR1cy5yYXBpZHNzbC5jb20wPgYIKwYBBQUHMAKGMmh0dHA6Ly9jYWNl cnRzLnJhcGlkc3NsLmNvbS9SYXBpZFNTTFRMU1JTQUNBRzEuY3J0MAwGA1UdEwEB /wQCMAAwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB1AE51oydcmhDDOFts1N8/ Uusd8OCOG41pwLH6ZLFimjnfAAABkAFB2wcAAAQDAEYwRAIgD/tHwekd5qflWg/2 OmHBTtddyHd/cjXHLJV6Xtq1C5oCIFnsKrsvu6yiM2WuK5/MaEvOaSUh1MaRFrX5 DPaOBC2vAHYAfVkeEuF4KnscYWd8Xv340IdcFKBOlZ65Ay/ZDowuebgAAAGQAUHa jQAABAMARzBFAiEAvO4+Keg5Ct1FvN9O97OUSRMpjWjwG7fxC2pxA3jb9ZcCIBim P2JMtVThyAXvik38J+j1R7gPum91ZTiRO7nD5BNlAHcA5tIxY0B3jMEQQQbXcbnO wdJA9paEhvu6hzId/R43jlAAAAGQAUHaogAABAMASDBGAiEA1qzMkCmpRjo0pl/X qpWxjp0I6d86YRzgi8Ob2G+N+MACIQC8v3tdoESB3rKv9d1wd6GCayNSoR8HIeUS 0NmCog6lqzANBgkqhkiG9w0BAQsFAAOCAQEAdVFaeTVq1pWcNFrcHPQMfxTD3HNO S4TVAv1C9lTojhvr8scTotSa7wO+ph3XIQMvPYMStOvZrlZUZf/RKE+My9i4UNn6 wsGucwmiRmpUO9fZ7B3rg+BtUJHpbcQtuTWNKu2KSCLD5sC15fJ59W/XTJ9OfrvN 02uWoGexFJ6ZLFbESD5uHqB8nAJvOAdNZa/N+6Lv5NOVkvtnTdTkE3/vKk1AoGNu PeXtwU/Q0F3LsSfXiwk0DjInekw0wRSoiMQBiBPR6xgkr3xbSTesyR2ckHIhq8j+ HVh1jcNHVmvpjbCsFD/QgOhTtrE1qWeBn5UNqT6npr6ntkSvjrH15CgYTg== -----END CERTIFICATE-----)"; QSslConfiguration sslConfiguration = QSslConfiguration::defaultConfiguration(); qDebug() << "Number of CA certs: " << sslConfiguration.caCertificates().size(); for (const auto & c : sslConfiguration.caCertificates()) { qDebug() << qPrintable(c.toPem()); } auto caCert = QSslCertificate::fromData(cert); sslConfiguration.addCaCertificates(caCert); qDebug() << "Number of CA certs: " << sslConfiguration.caCertificates().size(); for (const auto & c : sslConfiguration.caCertificates()) { qDebug() << qPrintable(c.toPem()); } request.setSslConfiguration(sslConfiguration); m_netAccessManager->get(request);
The result is:
21:25:12.064 [D] default: "OpenSSL 3.3.1 4 Jun 2024" 21:25:12.066 [D] default: Number of CA certs: 0 21:25:12.067 [D] default: Number of CA certs: 1 21:25:12.067 [D] default: -----BEGIN CERTIFICATE----- MIIGJzCCBQ+gAwIBAgIQAq2BXDbORNVanb6A/36zgjANBgkqhkiG9w0BAQsFADBg MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMR8wHQYDVQQDExZSYXBpZFNTTCBUTFMgUlNBIENBIEcx MB4XDTI0MDYxMDAwMDAwMFoXDTI1MDYwOTIzNTk1OVowGDEWMBQGA1UEAwwNKi5k YWJsaXN0Lm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMgNZkE4 aQbP5npnaycnZY5QwaCFqOC1hEQCs/gqiTba46KunrYeWngf6ObA0QZbAIBZsnIq 1lad/GwicptYJHvNICOy9/vuDHbmD/gMgGzvzhApG0euNYnGMf3OOwvQN2vf7DCk M3GxDTzQqWJaVSkFyFQjjZywT1mhfdL7Q93fCPLdTEwhRAqGQ3y8RKnnducRI8ZG 0ZSydKq9991WClO0WUbnMctMBlRnQW4U55FtQEEgmVS+Waiy8UhyGj3Dj/sSlcgD H66dkYFebkps36e2CJL26UyV8CPBHddQgEDv8GKwhBNS0PFVHad08N/PbpH0nNse Q8T/YOmscq6BsoUCAwEAAaOCAyMwggMfMB8GA1UdIwQYMBaAFAzbbIJJD0pnCrgU 7nrESFKI61Y4MB0GA1UdDgQWBBTUjdJOwkm7oOW9UKg8Ilplh2WoITAlBgNVHREE HjAcgg0qLmRhYmxpc3Qub3JnggtkYWJsaXN0Lm9yZzA+BgNVHSAENzA1MDMGBmeB DAECATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA/ BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY2RwLnJhcGlkc3NsLmNvbS9SYXBpZFNT TFRMU1JTQUNBRzEuY3JsMHYGCCsGAQUFBwEBBGowaDAmBggrBgEFBQcwAYYaaHR0 cDovL3N0YXR1cy5yYXBpZHNzbC5jb20wPgYIKwYBBQUHMAKGMmh0dHA6Ly9jYWNl cnRzLnJhcGlkc3NsLmNvbS9SYXBpZFNTTFRMU1JTQUNBRzEuY3J0MAwGA1UdEwEB /wQCMAAwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB1AE51oydcmhDDOFts1N8/ Uusd8OCOG41pwLH6ZLFimjnfAAABkAFB2wcAAAQDAEYwRAIgD/tHwekd5qflWg/2 OmHBTtddyHd/cjXHLJV6Xtq1C5oCIFnsKrsvu6yiM2WuK5/MaEvOaSUh1MaRFrX5 DPaOBC2vAHYAfVkeEuF4KnscYWd8Xv340IdcFKBOlZ65Ay/ZDowuebgAAAGQAUHa jQAABAMARzBFAiEAvO4+Keg5Ct1FvN9O97OUSRMpjWjwG7fxC2pxA3jb9ZcCIBim P2JMtVThyAXvik38J+j1R7gPum91ZTiRO7nD5BNlAHcA5tIxY0B3jMEQQQbXcbnO wdJA9paEhvu6hzId/R43jlAAAAGQAUHaogAABAMASDBGAiEA1qzMkCmpRjo0pl/X qpWxjp0I6d86YRzgi8Ob2G+N+MACIQC8v3tdoESB3rKv9d1wd6GCayNSoR8HIeUS 0NmCog6lqzANBgkqhkiG9w0BAQsFAAOCAQEAdVFaeTVq1pWcNFrcHPQMfxTD3HNO S4TVAv1C9lTojhvr8scTotSa7wO+ph3XIQMvPYMStOvZrlZUZf/RKE+My9i4UNn6 wsGucwmiRmpUO9fZ7B3rg+BtUJHpbcQtuTWNKu2KSCLD5sC15fJ59W/XTJ9OfrvN 02uWoGexFJ6ZLFbESD5uHqB8nAJvOAdNZa/N+6Lv5NOVkvtnTdTkE3/vKk1AoGNu PeXtwU/Q0F3LsSfXiwk0DjInekw0wRSoiMQBiBPR6xgkr3xbSTesyR2ckHIhq8j+ HVh1jcNHVmvpjbCsFD/QgOhTtrE1qWeBn5UNqT6npr6ntkSvjrH15CgYTg== -----END CERTIFICATE----- 21:25:12.158 [D] default: "The issuer certificate of a locally looked up certificate could not be found" 21:25:12.158 [D] default: "No certificates could be verified" 21:25:12.158 [D] default: QNetworkReply::SslHandshakeFailedError
So it seems that certificate is added but not working. And furthermore I am surprised that there are no certificates in default configuration:
21:25:12.066 [D] default: Number of CA certs: 0
What am I doing wrong?
By the way: it seems to be the same problem in Windows and there is not problem with CA certificate under macOS
-
OK, I can load CA certificates from system and then append the additional certificate from QByteArray but I still cannot connect to the server:
QSslConfiguration sslConfiguration = QSslConfiguration::defaultConfiguration(); sslConfiguration.setCaCertificates(QSslConfiguration::systemCaCertificates());
The result is still:
21:53:38.349 [D] default: "OpenSSL 3.3.1 4 Jun 2024" 21:53:38.391 [D] default: Number of CA certs: 296 21:53:38.391 [D] default: Number of CA certs: 297 21:53:38.491 [D] default: "The issuer certificate of a locally looked up certificate could not be found" 21:53:38.491 [D] default: "No certificates could be verified" 21:53:38.491 [D] default: QNetworkReply::SslHandshakeFailedError
I have tried to load the certificate from the same file as I use for curl and the result is still the same :-(
EDIT: I did a mistake. I was actually adding server certificate instead for CA certificate. When I did further analysis I found out that content of cacert.crt was exactly the same I got in the sslErrors slot as peer certificate:
connect(m_netAccessManager, &QNetworkAccessManager::sslErrors, this, [this](QNetworkReply *reply, const QList<QSslError> &errors) { for (const auto & e : errors) { qDebug() << e; } QSslConfiguration sslConf = reply->sslConfiguration(); QSslCertificate sslCert = sslConf.peerCertificate(); });
So after providing CA certificate it works. I just do not understand why it was working with curl :-(
-
Hi,
One thing that I find strange in your certificate are the parentheses. I don't remember seeing these chars in certificates.
-
Hi,
It is raw literal string syntax according to C++ standard: https://en.cppreference.com/w/cpp/language/string_literal
And it seems to work correctly because the debug log displays the expected contents of certificate. -
Hi,
One thing that I find strange in your certificate are the parentheses. I don't remember seeing these chars in certificates.
@SGaist said in How to add CA certificate to QSslConfiguration:
Hi,
One thing that I find strange in your certificate are the parentheses. I don't remember seeing these chars in certificates.
Raw string literal, eg
R"(string with " in the middle)";
-
First of all, I want apologize for probably stupid question.
I need to download file from a HTTPS server. The problem is that server uses CA certificate (Digicert) that is not recognized by Linux although it works fine in browser. If I run:curl --verbose https://server/file
I get this error:
curl: (60) SSL certificate problem: unable to get local issuer certificate
So I have downloaded CA certificate to cacert.crt file and after providing that certificate to curl, it works and firl is downloaded:
curl --verbose https://server/file --cacert cacert.crt
Now, I want to achieve the same in Qt 6 but so far without any success. I am trying to add CA cert to QSslConfiguration but it does not work:
QByteArray cert = R"(-----BEGIN CERTIFICATE----- MIIGJzCCBQ+gAwIBAgIQAq2BXDbORNVanb6A/36zgjANBgkqhkiG9w0BAQsFADBg MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMR8wHQYDVQQDExZSYXBpZFNTTCBUTFMgUlNBIENBIEcx MB4XDTI0MDYxMDAwMDAwMFoXDTI1MDYwOTIzNTk1OVowGDEWMBQGA1UEAwwNKi5k YWJsaXN0Lm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMgNZkE4 aQbP5npnaycnZY5QwaCFqOC1hEQCs/gqiTba46KunrYeWngf6ObA0QZbAIBZsnIq 1lad/GwicptYJHvNICOy9/vuDHbmD/gMgGzvzhApG0euNYnGMf3OOwvQN2vf7DCk M3GxDTzQqWJaVSkFyFQjjZywT1mhfdL7Q93fCPLdTEwhRAqGQ3y8RKnnducRI8ZG 0ZSydKq9991WClO0WUbnMctMBlRnQW4U55FtQEEgmVS+Waiy8UhyGj3Dj/sSlcgD H66dkYFebkps36e2CJL26UyV8CPBHddQgEDv8GKwhBNS0PFVHad08N/PbpH0nNse Q8T/YOmscq6BsoUCAwEAAaOCAyMwggMfMB8GA1UdIwQYMBaAFAzbbIJJD0pnCrgU 7nrESFKI61Y4MB0GA1UdDgQWBBTUjdJOwkm7oOW9UKg8Ilplh2WoITAlBgNVHREE HjAcgg0qLmRhYmxpc3Qub3JnggtkYWJsaXN0Lm9yZzA+BgNVHSAENzA1MDMGBmeB DAECATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA/ BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY2RwLnJhcGlkc3NsLmNvbS9SYXBpZFNT TFRMU1JTQUNBRzEuY3JsMHYGCCsGAQUFBwEBBGowaDAmBggrBgEFBQcwAYYaaHR0 cDovL3N0YXR1cy5yYXBpZHNzbC5jb20wPgYIKwYBBQUHMAKGMmh0dHA6Ly9jYWNl cnRzLnJhcGlkc3NsLmNvbS9SYXBpZFNTTFRMU1JTQUNBRzEuY3J0MAwGA1UdEwEB /wQCMAAwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB1AE51oydcmhDDOFts1N8/ Uusd8OCOG41pwLH6ZLFimjnfAAABkAFB2wcAAAQDAEYwRAIgD/tHwekd5qflWg/2 OmHBTtddyHd/cjXHLJV6Xtq1C5oCIFnsKrsvu6yiM2WuK5/MaEvOaSUh1MaRFrX5 DPaOBC2vAHYAfVkeEuF4KnscYWd8Xv340IdcFKBOlZ65Ay/ZDowuebgAAAGQAUHa jQAABAMARzBFAiEAvO4+Keg5Ct1FvN9O97OUSRMpjWjwG7fxC2pxA3jb9ZcCIBim P2JMtVThyAXvik38J+j1R7gPum91ZTiRO7nD5BNlAHcA5tIxY0B3jMEQQQbXcbnO wdJA9paEhvu6hzId/R43jlAAAAGQAUHaogAABAMASDBGAiEA1qzMkCmpRjo0pl/X qpWxjp0I6d86YRzgi8Ob2G+N+MACIQC8v3tdoESB3rKv9d1wd6GCayNSoR8HIeUS 0NmCog6lqzANBgkqhkiG9w0BAQsFAAOCAQEAdVFaeTVq1pWcNFrcHPQMfxTD3HNO S4TVAv1C9lTojhvr8scTotSa7wO+ph3XIQMvPYMStOvZrlZUZf/RKE+My9i4UNn6 wsGucwmiRmpUO9fZ7B3rg+BtUJHpbcQtuTWNKu2KSCLD5sC15fJ59W/XTJ9OfrvN 02uWoGexFJ6ZLFbESD5uHqB8nAJvOAdNZa/N+6Lv5NOVkvtnTdTkE3/vKk1AoGNu PeXtwU/Q0F3LsSfXiwk0DjInekw0wRSoiMQBiBPR6xgkr3xbSTesyR2ckHIhq8j+ HVh1jcNHVmvpjbCsFD/QgOhTtrE1qWeBn5UNqT6npr6ntkSvjrH15CgYTg== -----END CERTIFICATE-----)"; QSslConfiguration sslConfiguration = QSslConfiguration::defaultConfiguration(); qDebug() << "Number of CA certs: " << sslConfiguration.caCertificates().size(); for (const auto & c : sslConfiguration.caCertificates()) { qDebug() << qPrintable(c.toPem()); } auto caCert = QSslCertificate::fromData(cert); sslConfiguration.addCaCertificates(caCert); qDebug() << "Number of CA certs: " << sslConfiguration.caCertificates().size(); for (const auto & c : sslConfiguration.caCertificates()) { qDebug() << qPrintable(c.toPem()); } request.setSslConfiguration(sslConfiguration); m_netAccessManager->get(request);
The result is:
21:25:12.064 [D] default: "OpenSSL 3.3.1 4 Jun 2024" 21:25:12.066 [D] default: Number of CA certs: 0 21:25:12.067 [D] default: Number of CA certs: 1 21:25:12.067 [D] default: -----BEGIN CERTIFICATE----- MIIGJzCCBQ+gAwIBAgIQAq2BXDbORNVanb6A/36zgjANBgkqhkiG9w0BAQsFADBg MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMR8wHQYDVQQDExZSYXBpZFNTTCBUTFMgUlNBIENBIEcx MB4XDTI0MDYxMDAwMDAwMFoXDTI1MDYwOTIzNTk1OVowGDEWMBQGA1UEAwwNKi5k YWJsaXN0Lm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMgNZkE4 aQbP5npnaycnZY5QwaCFqOC1hEQCs/gqiTba46KunrYeWngf6ObA0QZbAIBZsnIq 1lad/GwicptYJHvNICOy9/vuDHbmD/gMgGzvzhApG0euNYnGMf3OOwvQN2vf7DCk M3GxDTzQqWJaVSkFyFQjjZywT1mhfdL7Q93fCPLdTEwhRAqGQ3y8RKnnducRI8ZG 0ZSydKq9991WClO0WUbnMctMBlRnQW4U55FtQEEgmVS+Waiy8UhyGj3Dj/sSlcgD H66dkYFebkps36e2CJL26UyV8CPBHddQgEDv8GKwhBNS0PFVHad08N/PbpH0nNse Q8T/YOmscq6BsoUCAwEAAaOCAyMwggMfMB8GA1UdIwQYMBaAFAzbbIJJD0pnCrgU 7nrESFKI61Y4MB0GA1UdDgQWBBTUjdJOwkm7oOW9UKg8Ilplh2WoITAlBgNVHREE HjAcgg0qLmRhYmxpc3Qub3JnggtkYWJsaXN0Lm9yZzA+BgNVHSAENzA1MDMGBmeB DAECATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA/ BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY2RwLnJhcGlkc3NsLmNvbS9SYXBpZFNT TFRMU1JTQUNBRzEuY3JsMHYGCCsGAQUFBwEBBGowaDAmBggrBgEFBQcwAYYaaHR0 cDovL3N0YXR1cy5yYXBpZHNzbC5jb20wPgYIKwYBBQUHMAKGMmh0dHA6Ly9jYWNl cnRzLnJhcGlkc3NsLmNvbS9SYXBpZFNTTFRMU1JTQUNBRzEuY3J0MAwGA1UdEwEB /wQCMAAwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB1AE51oydcmhDDOFts1N8/ Uusd8OCOG41pwLH6ZLFimjnfAAABkAFB2wcAAAQDAEYwRAIgD/tHwekd5qflWg/2 OmHBTtddyHd/cjXHLJV6Xtq1C5oCIFnsKrsvu6yiM2WuK5/MaEvOaSUh1MaRFrX5 DPaOBC2vAHYAfVkeEuF4KnscYWd8Xv340IdcFKBOlZ65Ay/ZDowuebgAAAGQAUHa jQAABAMARzBFAiEAvO4+Keg5Ct1FvN9O97OUSRMpjWjwG7fxC2pxA3jb9ZcCIBim P2JMtVThyAXvik38J+j1R7gPum91ZTiRO7nD5BNlAHcA5tIxY0B3jMEQQQbXcbnO wdJA9paEhvu6hzId/R43jlAAAAGQAUHaogAABAMASDBGAiEA1qzMkCmpRjo0pl/X qpWxjp0I6d86YRzgi8Ob2G+N+MACIQC8v3tdoESB3rKv9d1wd6GCayNSoR8HIeUS 0NmCog6lqzANBgkqhkiG9w0BAQsFAAOCAQEAdVFaeTVq1pWcNFrcHPQMfxTD3HNO S4TVAv1C9lTojhvr8scTotSa7wO+ph3XIQMvPYMStOvZrlZUZf/RKE+My9i4UNn6 wsGucwmiRmpUO9fZ7B3rg+BtUJHpbcQtuTWNKu2KSCLD5sC15fJ59W/XTJ9OfrvN 02uWoGexFJ6ZLFbESD5uHqB8nAJvOAdNZa/N+6Lv5NOVkvtnTdTkE3/vKk1AoGNu PeXtwU/Q0F3LsSfXiwk0DjInekw0wRSoiMQBiBPR6xgkr3xbSTesyR2ckHIhq8j+ HVh1jcNHVmvpjbCsFD/QgOhTtrE1qWeBn5UNqT6npr6ntkSvjrH15CgYTg== -----END CERTIFICATE----- 21:25:12.158 [D] default: "The issuer certificate of a locally looked up certificate could not be found" 21:25:12.158 [D] default: "No certificates could be verified" 21:25:12.158 [D] default: QNetworkReply::SslHandshakeFailedError
So it seems that certificate is added but not working. And furthermore I am surprised that there are no certificates in default configuration:
21:25:12.066 [D] default: Number of CA certs: 0
What am I doing wrong?
By the way: it seems to be the same problem in Windows and there is not problem with CA certificate under macOS
@KejPi said in How to add CA certificate to QSslConfiguration:
21:25:12.158 [D] default: "The issuer certificate of a locally looked up certificate could not be found"
The TLS layer is attempting to validate the certificate authority used for this certificate. The code above is registering this certificate as a CA, but the certificate isn't being used to sign another.
This can be worked around by connecting to the sslErrors signal, and ignoring the error in question.
(or import the CA certificate) -
It is actually the CA certificate that shall be used to validate server certificate because this works as expected (cacert.crt is the same certificate in my code example):
curl --verbose https://server/file --cacert cacert.crt
And the other think - why there are no CA certificates by default? I would assume that default configuration contains at least all CA certificates that are installed in system.
@jeremy_k said in How to add CA certificate to QSslConfiguration:
This can be worked around by connecting to the sslErrors signal, and ignoring the error in question.
(or import the CA certificate)How can I import the CA certificate? I am actually trying to do it but probably wrong way.
-
It is actually the CA certificate that shall be used to validate server certificate because this works as expected (cacert.crt is the same certificate in my code example):
curl --verbose https://server/file --cacert cacert.crt
And the other think - why there are no CA certificates by default? I would assume that default configuration contains at least all CA certificates that are installed in system.
@jeremy_k said in How to add CA certificate to QSslConfiguration:
This can be worked around by connecting to the sslErrors signal, and ignoring the error in question.
(or import the CA certificate)How can I import the CA certificate? I am actually trying to do it but probably wrong way.
@KejPi said in How to add CA certificate to QSslConfiguration:
How can I import the CA certificate?
From a file, directly? Constructor accepts QIODevice: https://doc.qt.io/qt-6/qsslcertificate.html#QSslCertificate
The problem might be the format https://doc.qt.io/qt-6/qssl.html#EncodingFormat-enum - I am not sure if CRT is acceptable, I always load PEM.@KejPi said in How to add CA certificate to QSslConfiguration:
And furthermore I am surprised that there are no certificates in default configuration
Are you on macOS perhaps? From: https://doc.qt.io/qt-6/qsslsocket.html
Note: If available, root certificates on Unix (excluding macOS) will be loaded on demand from the standard certificate directories. If you do not want to load root certificates on demand, you need to call either QSslConfiguration::defaultConfiguration().setCaCertificates() before the first SSL handshake is made in your application (for example, via passing QSslSocket::systemCaCertificates() to it), or call QSslConfiguration::defaultConfiguration()::setCaCertificates() on your QSslSocket instance prior to the SSL handshake.
-
@KejPi said in How to add CA certificate to QSslConfiguration:
How can I import the CA certificate?
From a file, directly? Constructor accepts QIODevice: https://doc.qt.io/qt-6/qsslcertificate.html#QSslCertificate
The problem might be the format https://doc.qt.io/qt-6/qssl.html#EncodingFormat-enum - I am not sure if CRT is acceptable, I always load PEM.@KejPi said in How to add CA certificate to QSslConfiguration:
And furthermore I am surprised that there are no certificates in default configuration
Are you on macOS perhaps? From: https://doc.qt.io/qt-6/qsslsocket.html
Note: If available, root certificates on Unix (excluding macOS) will be loaded on demand from the standard certificate directories. If you do not want to load root certificates on demand, you need to call either QSslConfiguration::defaultConfiguration().setCaCertificates() before the first SSL handshake is made in your application (for example, via passing QSslSocket::systemCaCertificates() to it), or call QSslConfiguration::defaultConfiguration()::setCaCertificates() on your QSslSocket instance prior to the SSL handshake.
@artwaw said in How to add CA certificate to QSslConfiguration:
From a file, directly? Constructor accepts QIODevice: https://doc.qt.io/qt-6/qsslcertificate.html#QSslCertificate
I am importing it from QByteArray and it does not seem to work as expected:
auto caCert = QSslCertificate::fromData(cert);
PEM is text base64 encoded certificate and DER is binary, crt is only an extension. I think that the certificate in my code is PEM format and it should work as it does in curl command.
@artwaw said in How to add CA certificate to QSslConfiguration:
call either QSslConfiguration::defaultConfiguration().setCaCertificates() before the first SSL handshake is made in your application (for example, via passing QSslSocket::systemCaCertificates() to it), or call QSslConfiguration::defaultConfiguration()::setCaCertificates() on your QSslSocket instance prior to the SSL handshake
Thanks for this hint, I will try that, maybe this is the roocause for the problem because my QSslConfiguration contains only singe CA certificate loaded from QByteArray and I would say other CA certificate from system could be required to complete chain validation.
-
OK, I can load CA certificates from system and then append the additional certificate from QByteArray but I still cannot connect to the server:
QSslConfiguration sslConfiguration = QSslConfiguration::defaultConfiguration(); sslConfiguration.setCaCertificates(QSslConfiguration::systemCaCertificates());
The result is still:
21:53:38.349 [D] default: "OpenSSL 3.3.1 4 Jun 2024" 21:53:38.391 [D] default: Number of CA certs: 296 21:53:38.391 [D] default: Number of CA certs: 297 21:53:38.491 [D] default: "The issuer certificate of a locally looked up certificate could not be found" 21:53:38.491 [D] default: "No certificates could be verified" 21:53:38.491 [D] default: QNetworkReply::SslHandshakeFailedError
I have tried to load the certificate from the same file as I use for curl and the result is still the same :-(
EDIT: I did a mistake. I was actually adding server certificate instead for CA certificate. When I did further analysis I found out that content of cacert.crt was exactly the same I got in the sslErrors slot as peer certificate:
connect(m_netAccessManager, &QNetworkAccessManager::sslErrors, this, [this](QNetworkReply *reply, const QList<QSslError> &errors) { for (const auto & e : errors) { qDebug() << e; } QSslConfiguration sslConf = reply->sslConfiguration(); QSslCertificate sslCert = sslConf.peerCertificate(); });
So after providing CA certificate it works. I just do not understand why it was working with curl :-(
-