Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Using SSL client certificate
QtWS25 Last Chance

Using SSL client certificate

Scheduled Pinned Locked Moved General and Desktop
4 Posts 2 Posters 18.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    martonmiklos
    wrote on 7 Oct 2013, 18:01 last edited by
    #1

    Hello all,

    I would like to communicate with a webservice which requires client side certificate based authentication.
    The certificate comes in PKCS12# format.

    I have been able to extract the client certificate using openssl:
    @openssl pkcs12 -in 24d5bfcdbd55623894351e0dcdd6aee4f1a04a3d -clcerts -out x509.pem@

    My test code can be found below which reads the extracted certificate and tries to connect to the server:
    @QFile certFile("/home/mm/Projektek/qt/qtrafik/soap/certs/x509");
    certFile.open(QFile::ReadOnly);
    QSslCertificate cert(&certFile);
    certFile.close();

    qWarning() << cert.expiryDate() << cert.version() << cert.serialNumber() << cert.isNull() << cert.issuerInfo(QSslCertificate::Organization);
    qWarning() << cert.toText();
    QSslConfiguration configuration; 
    configuration.setLocalCertificate(cert);
    qWarning() << configuration.localCertificate().serialNumber();
    
    QNetworkRequest request;
    request.setSslConfiguration(configuration);
    request.setUrl(QUrl("https://adatkuldes-teszt.nemzetidohany.gov.hu:8444/nd/MasterData.svc?wsdl"));
    
    reply = manager->get(request);
    connect(reply, SIGNAL(readyRead()), this, SLOT(readyRead()));
    connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
    connect(reply, SIGNAL(finished()), this, SLOT(finished()));@
    

    The loaded certificate information (cert.toText();) correlates 100% with the certificate details in the Firefox (I have been able to load the cert to my browser and access the server).

    Unfortunatelly my QNetworkManager emits the error(QNetworkReply::NetworkError) signal with 99 (QNetworkReply::UnknownNetworkError) error code with "Unable to init SSL Context: " errorString().

    I am working with Qt 5.0.1 on kUbuntu 13.04 64 bit.
    I have openssl installed, and the QSslSocket::supportsSsl() returns true.

    Any help, suggestion or hint will be highly appericiated!

    1 Reply Last reply
    1
    • M Offline
      M Offline
      martonmiklos
      wrote on 9 Oct 2013, 18:15 last edited by
      #2

      I have compiled my test project with Qt 4.8.4, and it resulted a different error message:

      @Cannot provide a certificate with no key, @

      After some searching I realized that I have to extract the CA cert, and the private key from my PKCS12# file with openssl, and load them to my QSslConfiguration.

      To save it to the posterity this is how it is working for me now:

      @
      openssl pkcs12 -in 24d5bfcdbd55623894351e0dcdd6aee4f1a04a3d -clcerts -out clientcert.pem
      openssl pkcs12 -in 24d5bfcdbd55623894351e0dcdd6aee4f1a04a3d -nocerts -out privkey.key
      openssl pkcs12 -in 24d5bfcdbd55623894351e0dcdd6aee4f1a04a3d -cacerts -out cacert.pem
      @

      At the extraction of the private key I have given 1234 as password (see the code below.)

      @ QSslConfiguration configuration;

      QFile certFile&#40;"/home/mm/Projektek/qt/qtrafik/soap/certs/clientcert.pem"&#41;;
      certFile.open(QFile::ReadOnly&#41;;
      QSslCertificate cert(&certFile);
      certFile.close();
      configuration.setLocalCertificate(cert);
      
      QList<QSslCertificate> certs;
      certFile.setFileName("/home/mm/Projektek/qt/qtrafik/soap/certs/cacert.pem");
      certFile.open(QFile::ReadOnly);
      QSslCertificate caCert(&certFile);
      certFile.close();
      certs.append(caCert);
      configuration.setCaCertificates(certs);
      
      QFile keyFile&#40;"/home/mm/Projektek/qt/qtrafik/soap/certs/privkey.key"&#41;;
      keyFile.open(QFile::ReadOnly&#41;;
      QSslKey key(&keyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "1234");
      qWarning() << key.isNull();
      configuration.setPrivateKey(key);
      keyFile.close();
      
      QNetworkRequest request;
      request.setSslConfiguration(configuration);
      request.setUrl(QUrl("https://adatkuldes-teszt.nemzetidohany.gov.hu:8444/nd/MasterData.svc?wsdl"));
      reply = manager->get(request);
      connect(reply, SIGNAL(readyRead()), this, SLOT(readyRead()));
      connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
      connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
      connect(reply, SIGNAL(finished()), this, SLOT(finished()));@
      
      1 Reply Last reply
      1
      • M Offline
        M Offline
        martonmiklos
        wrote on 11 Jan 2014, 13:47 last edited by
        #3

        I have been able to create a more sophisticated solution using the QCA (Qt cryptographics architecture see: http://delta.affinix.com/qca/). To be able to use it with Qt5 download the latest version of the code from here:
        git://anongit.kde.org/qca.git

        My SSL configuration initialization code is the following:
        @//initialize QCA
        QCA::init();

        if (QFile::exists(m_certificatePath)) {
            QCA::KeyBundle bundle(m_certificatePath, QCA::SecureArray(m_certificatePassword.toLocal8Bit()));
        
            QList<QSslCertificate> CACerts;
            foreach (QCA::Certificate cert, bundle.certificateChain()) {
                if (cert.isCA()) {
                    QSslCertificate CACertificate(cert.toPEM().toLocal8Bit(), QSsl::Pem);
                    CACerts.append(CACertificate);
                } else {
                    m_SSLConfiguration.setLocalCertificate(QSslCertificate(cert.toPEM().toLocal8Bit(), QSsl::Pem));
                }
            }
        
            m_SSLConfiguration.setCaCertificates(CACerts);
        
            QSslKey key(bundle.privateKey().toDER().toByteArray(), QSsl::Rsa, QSsl::Der);
            m_SSLConfiguration.setPrivateKey(key);
        }@
        

        The application have to be linked with the QCA libraries (-lqca) and the Qt library search path have to contain the "crypto" folder of the compiled QCA library.

        1 Reply Last reply
        1
        • J Offline
          J Offline
          jeremiah
          wrote on 7 Jan 2016, 21:11 last edited by
          #4

          here is a clean way i used without a 3rd party lib.

          bool loadPfxCertifcate(QString certFilename, QString passphrase) {
          
              QFile certFile(certFilename);
              certFile.open(QFile::ReadOnly);
              QSslCertificate certificate;
              QSslKey key;
              QList<QSslCertificate> importedCerts;
          
              bool imported = QSslCertificate::importPkcs12(&certFile, &key, &certificate, &importedCerts, QByteArray::fromStdString(passphrase.toStdString()));
          
              certFile.close();
          
              qDebug() << "Imported cert:" << imported;
          
              if (imported) {
                  QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
                  QList<QSslCertificate> certs = sslConfig.caCertificates();
                  QList<QSslCertificate> localCerts = sslConfig.localCertificateChain();
                  localCerts.append(certificate);
                  certs.append(importedCerts);
          
                  sslConfig.setLocalCertificateChain(localCerts);
                  sslConfig.setCaCertificates(certs);
                  sslConfig.setPrivateKey(key);
                  QSslConfiguration::setDefaultConfiguration(sslConfig);
              }
          
              return imported;
          }
          
          1 Reply Last reply
          1

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved