OpenSSL with QML Image source. Self signed ca-certificate
-
The purpose of this topic is to get rid of error: "QML Image: SSL handshake failed: The issuer certificate of a locally looked up certificate could not be found" when loading image in qml.
It seems impossible to load image in qml from ssl protected source with self signed ca-certificate even if openssl lib linked with application. Example is below.
- Create an qml app.
- Handle build and runtime ssl versions > 3.
#include <QSslSocket> ... qDebug() << "Build SSL version:" << QSslSocket::sslLibraryBuildVersionString(); qDebug() << "Run SSL version:" << QSslSocket::sslLibraryVersionString();
- Add image in qml.
import QtQuick Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Image { anchors.fill: parent source: "some_https_ssl_tls_url" } }
My output for checking ssl versions os ok:
Build SSL version: "OpenSSL 3.0.7 1 Nov 2022" Run SSL version: "OpenSSL 3.0.2 15 Mar 2022"
but i still getting this error.
QML Image: SSL handshake failed: The issuer certificate of a locally looked up certificate could not be found
I have http setup for image server, and it works fine without ssl etc. And of course I understand that i can just create a simple class with NetworkAccessManager, setup my certificate to sslconfig and it will works. But i'm just curious, is it possible to load image from such source in QML?
-
Hi and welcome to devnet,
I think what you need is QQmlNetworkAccessManagerFactory.
-
@vinadenenko Hi .I have a solution.You can create a custom c++ class in the background with a network Access Manager.
Then you leave the image empty and give to the custom class the url to download(https://)
While downloading you will still get SLL hanshake failed.This time you can use QNetworkeply::ignoreSSlErrors(list_of_errors) to still continue with the request.
When the image has finished to download, give the QML Image the path to it or send that image as data to qml side.
thanks
-
@Ronel_qtmaster hi,
That's an overly complicated solution while Qt already offers the infrastructure required to do it.
Note that suggesting to ignore SSL errors in this context (and usually all of them) is a bad idea. The goal to use a custom certificate is to still have SSL protection so configuring the connection correctly is the right way to do it.
-
Thanks again @SGaist, works like a charm!
For anyone who will face this issue i provide a simple example.
- Define some
CustomNetworkAccessManager
(we need access to every request, because it is possible to setup our ownQSslConfiguration
only in request).
class CustomNetworkAccessManager : public QNetworkAccessManager { Q_OBJECT public: explicit CustomNetworkAccessManager(QObject *parent = nullptr) : QNetworkAccessManager{parent} { auto fileCert = QFile("/path/to/ca-certificate/example-cert.crt"); if (fileCert.open(QIODevice::ReadOnly)) { sslConfig_.addCaCertificate(QSslCertificate(&fileCert, QSsl::EncodingFormat::Pem)); } else { qDebug() << Q_FUNC_INFO << "Certificate file could not be opened!"; } fileCert.close(); } // QNetworkAccessManager interface protected: QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData = nullptr) override { QNetworkRequest req(request); req.setSslConfiguration(sslConfig_); return QNetworkAccessManager::createRequest(op, req, outgoingData); } private: QSslConfiguration sslConfig_; };
- Setup
CustomQmlNetworkAccessManagerFactory
with ourCustomNetworkAccessManager
.
class CustomQmlNetworkAccessManagerFactory : public QObject, public QQmlNetworkAccessManagerFactory { Q_OBJECT public: CustomQmlNetworkAccessManagerFactory() {} // QQmlNetworkAccessManagerFactory interface public: QNetworkAccessManager *create(QObject *parent) override { CustomNetworkAccessManager *networkAccessManager = new CustomNetworkAccessManager(parent); return networkAccessManager; } };
- Create the
CustomQmlNetworkAccessManagerFactory
and set it toQQmlApplicationEngine
:
CustomQmlNetworkAccessManagerFactory networkAccessManagerFactory; engine.setNetworkAccessManagerFactory(&networkAccessManagerFactory);
- Define some
-
-
The error you're encountering ("QML Image: SSL handshake failed") typically happens when there's a problem establishing a secure connection between the QML application and the server you're trying to connect to. This is often caused by issues with SSL certificates, the server's configuration, or network problems. To resolve this error, you can try the following steps:
Check SSL/TLS Configuration: Ensure that the server you're connecting to has a valid SSL certificate. If you're using a self-signed certificate, it may not be trusted by the system. Make sure the certificate is correctly installed.
Update QML/Qt and SSL Libraries: Sometimes, outdated libraries can cause compatibility issues. Make sure you're using the latest version of QML, Qt, and SSL libraries (OpenSSL).
Verify Network and Proxy Settings: If you're behind a proxy or firewall, ensure the settings are properly configured and not blocking the SSL handshake.
Trust Certificates: If the certificate isn't recognized by the system, you may need to manually add the certificate to the trust store.
Enable Debugging: You can enable debugging in Qt to get more information about the SSL handshake failure. Set the following environment variable before running your application:
ini
Copy
Edit
QT_DEBUG_PLUGINS=1
For more detailed information and troubleshooting, you can refer to the following resources:Qt SSL documentation
OpenSSL documentation
Common SSL handshake errors
Let me know if you need more help!