vincedjango
vincedjango

Reputation: 1046

The root certificate of the certificate chain is self-signed, and untrusted

I purchased a certificate on Godaddy. From them, I got three files: certificate.crt, certificatechain.crt, private.key

I have a QT app communicating with SSL to a Ubuntu server running Flask.

The website is working and running on https.

I don't have any problem on the Apache side,but here how I use the certificates.

In /etc/apache2/site-enabled/MyFlaskApp.conf

SSLEngine on
SSLCertificateFile      /etc/ssl/certificate.crt
SSLCertificateKeyFile   /etc/ssl/private.key
SSLCertificateChainFile /etc/ssl/certificatechain.crt

In QT:

void InitSSL()
{
    m_sslConfiguration.setProtocol(QSsl::TlsV1_2);

    // Set certificate to configuration
    QFile certFile;
    certFile.setFileName(path_certificate);
    if(certFile.open(QIODevice::ReadOnly))
    {
        QList<QSslCertificate> certificates;
        QSslCertificate certificate(&certFile, QSsl::Der);
        certificates.append(certificate);
        m_sslConfiguration.setCaCertificates(certificates);
    }

    QFile certChain;
    certChain.setFileName(path_certificate_chain);
    if(certChain.open(QIODevice::ReadOnly))
    {
        QList<QSslCertificate> certificates;
        QSslCertificate certificate(&certChain, QSsl::Der);
        certificates.append(certificate);
        m_sslConfiguration.setLocalCertificateChain(certificates);
    }

    QFile keyFile;
    keyFile.setFileName(DATABASE_PATH + DATABASE_KEY_PATH_SSL);
    if(keyFile.open(QIODevice::ReadOnly))
    {
        QSslKey key= QSslKey(keyFile.readAll(), QSsl::Rsa);
        m_sslConfiguration.setPrivateKey(key);
    }
}

I always get an SSL error saying, the root certificate of the certificate chain is self-signed, and untrusted".

It is not self signed, I purchased the certificate on GoDaddy.

Also, let me know what differences it makes if the QT app runs on Windows or Ubuntu.

Thanks

Upvotes: 1

Views: 4738

Answers (1)

talamaki
talamaki

Reputation: 5472

It looks like you are mixing the certificate file and the chain file in your code. You are setting the local certificate as a CA certificates chain and the CA certificates chain file as a full certificate chain. You also need to load all CA certificates from the chain file. I'm assuming that certificate.crt contains only the local certificate file and certificatechain.crt contains only the intermediate certificates and not the local certificate.

On the other hand, what are you trying to achieve? Have you enabled both client side and server side authentication because you are setting the local certificate and key on the client side? In that case you obviously should have two sets of certificates.

Anyway, you could try the following code to configure your Qt application. Qt is a cross-platform environment so there shouldn't be differences if you have configured the same openssl version on both platforms.

void InitSSL()
{
    m_sslConfiguration.setProtocol(QSsl::TlsV1_2);

    // Set certificate to configuration
    QFile certificate_file(path_certificate);
    if (!certificate_file.open(QIODevice::ReadOnly))
    {
        qWarning() << "error opening certificate file"
                   << QDir::current().absoluteFilePath(certificate_file.fileName());
        return;
    }

    QSslCertificate certificate(&certificate_file, QSsl::Der);
    certificate_file.close();
    if (!certificate.isValid())
    {
        qWarning() << "Certificate " << rCertificateFileName << " is not valid:"
                    << "valid from " << certificate.effectiveDate().toString("yyyy-MM-dd")
                    << " to " << certificate.expiryDate().toString("yyyy-MM-dd");
        return;
    }
    m_sslConfiguration.setLocalCertificate(certificate);

    // Set CA chain to configuration
    QList<QSslCertificate> ca_certificates = QSslCertificate::fromPath(path_certificate_chain, QSsl::Der);
    if (ca_certificates.isEmpty())
    {
        qWarning() << "error loading CA certificates from file " << path_certificate_chain;
        return;
    }
    m_sslConfiguration.setCaCertificates(ca_certificates);

    // Set key to configuration
    QString key_file_path(DATABASE_PATH + DATABASE_KEY_PATH_SSL);
    QFile key_file(key_file_path);
    if (!key_file.open(QIODevice::ReadOnly))
    {
        qWarning() << "Error opening key file "
                   << QDir::current().absoluteFilePath(key_file.fileName());
        return;
    }
    QSslKey key(&key_file, QSsl::Rsa);
    key_file.close();
    if (key.isNull())
    {
        qWarning() << "Key " << key_file_path << " is null";
        return;
    }
    m_sslConfiguration.setPrivateKey(key);
}

Instead of QSslCertificate::fromPath you can load CA certificates from the file also with QSslCertificate::fromData or QSslCertificate::fromDevice.

Are you sure the certificate files are in DER format? In case they are PEM you can remove QSsl::Der because QSsl::Pem is the default.

Upvotes: 2

Related Questions