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

Using SSL client certificate

Scheduled Pinned Locked Moved General and Desktop
4 Posts 2 Posters 18.2k 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 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 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 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 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