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. QNetwork: making queries using QSslConfiguration and PKCS12

QNetwork: making queries using QSslConfiguration and PKCS12

Scheduled Pinned Locked Moved Unsolved General and Desktop
sslpkcs12qnetwork
2 Posts 2 Posters 271 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.
  • P Offline
    P Offline
    plaristote
    wrote on last edited by
    #1

    Hi ! I'm trying to connect to a web service that uses PKCS12 to authentify its clients. There's a method in QSslConfiguration to import such certificates (importPkcs12), but I've been unsuccessful in using it properly: depending on the SSL protocol I select, the remote server either fails to complete the handshake (with TLSv1_0), or closes the connection (with any other protocol).

    I've made a small piece of code to reproduce the issue:

    #include <QApplication>
    #include <QNetworkAccessManager>
    #include <QNetworkRequest>
    #include <QNetworkReply>
    #include <QSslConfiguration>
    #include <QSslKey>
    #include <QJsonDocument>
    #include <QJsonObject>
    #include <QFile>
    
    int main(int argc, char** argv)
    {
      QApplication app(argc, argv);
      QNetworkAccessManager network;
      QNetworkRequest request;
      QNetworkReply* reply;
      QSslConfiguration sslConfiguration;
    
      //
      // load p12 certificate
      //
      QFile p12_certificate("Batuz_LROE_Ziurtagiriak_KIT_Certificados_V1_0_2/EnpresaZigilua_SelloDeEmpresa.p12");
      if (p12_certificate.open(QIODevice::ReadOnly))
      {
        QList<QSslCertificate> certificateChain;
        QSslCertificate certificate;
        QSslKey sslKey;
        QByteArray password("IZDesa2021");
    
        if (QSslCertificate::importPkcs12(&p12_certificate, &sslKey, &certificate, &certificateChain, password))
        {
          sslConfiguration.QSslConfiguration::defaultConfiguration();
          sslConfiguration.setProtocol(QSsl::AnyProtocol);
          sslConfiguration.setLocalCertificate(certificate);
          sslConfiguration.setLocalCertificateChain(certificateChain);
          sslConfiguration.setPrivateKey(sslKey);
          sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
        }
        else
          qDebug() << "failed to import p12 certificate";
      }
      else
        qDebug() << "failed to read p12 certificate";
    
      // eus-bizkaia-n3-data
      QJsonObject drs_data{
        {"ejer", "2022"}, {"mode", "240"}
      };
      QJsonObject inte_data{
        {"ap1", "John"}, {"ap2", "Doe"}, {"nif", "A12345678"}, {"nrs", "abcdefghijklmopqrstuvwxyzA6qLu"}
      };
      QJsonObject n3_data{
        {"apa", "1.1"}, {"con", "LROE"}, {"drs", drs_data}, {"inte", inte_data}
      };
    
      //
      // http headers
      //
      request.setUrl(QUrl("https://pruesarrerak.bizkaia.eus/N3B4000M/aurkezpena"));
      request.setSslConfiguration(sslConfiguration);
      request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");
      request.setHeader(QNetworkRequest::ContentLengthHeader, 10);
      request.setRawHeader("Content-Encoding", "gzip");
      request.setRawHeader("Accepted-Encoding", "gzip");
      request.setRawHeader("eus-bizkaia-n3-version", "1.0");
      request.setRawHeader("eus-bizkaia-n3-content-type", "application/xml");
      request.setRawHeader("eus-bizkaia-n3-data", QJsonDocument(n3_data).toJson());
    
      //
      // performing the query
      //
      reply = network.post(request, "0123456789");
      QObject::connect(reply, &QNetworkReply::finished, [reply]()
      {
        unsigned int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toUInt();
        qDebug() << "received response" << status;
        if (status != 200)
          qDebug() << "error:" << reply->errorString();
      });
      return app.exec();
    }
    

    It's designed to connect to the test environment for the LROE service (something from a local government in Spain).
    The sample certificate used in this code can be found in the following archive:
    https://www.batuz.eus/fitxategiak/batuz/lroe/batuz_lroe_ziurtagiriak_kit_certificados_v1_0_2.7z

    I found an implementation of this service developed in Python, and I've refactored it into a small program to check if I was able to get things working with what I had at hand. I believe the following code should do the same thing as the Qt program above... yet this one actually works:

    # Must install request_pkcs12 using "pip install requests-pkcs12"
    
    from requests_pkcs12 import post as pkcs12_post
    import json
    
    # eus-bizkaia-n3-data
    data = {}
    data["apa"] = "1.1"
    data["con"] = "LROE"
    data["drs"] = {}
    data["drs"]["ejer"] = "2022"
    data["drs"]["mode"] = "240"
    data["inte"] = {}
    data["inte"]["ap1"] = "John"
    data["inte"]["ap2"] = "Doe"
    data["inte"]["nif"] = "A99805061"
    data["inte"]["nrs"] = "5Yd5j4iyKM7qjJnDKVAptFTF6A6qLu"
    
    # http headers
    headers = {}
    headers["Content-Type"] = "application/octet-stream"
    headers["Content-Length"] = "802332"
    headers["Content-Encoding"] = "gzip"
    headers["eus-bizkaia-n3-version"] = "1.0"
    headers["eus-bizkaia-n3-content-type"] = "application/xml"
    headers["eus-bizkaia-n3-data"] = "{}"
    
    # p12 certificate
    p12_password = "IZDesa2021"
    p12_buffer = open("Batuz_LROE_Ziurtagiriak_KIT_Certificados_V1_0_2/EnpresaZigilua_SelloDeEmpresa.p12", "rb").read()
    
    # performing the query
    response = pkcs12_post(
      "http://pruesarrerak.bizkaia.eus/N3B4000M/aurkezpena",
      data="0123456789",
      headers=headers,
      pkcs12_data=p12_buffer,
      pkcs12_password=p12_password
    )
    

    So, worst case scenario, I can just write a Python program that I'll call from my Qt program.
    But I'd much rather perform these tasks entirely in Qt. So here's a bottle thrown into the ocean, hoping to find the help that I so desperately need !

    1 Reply Last reply
    0
    • C Offline
      C Offline
      ChrisW67
      wrote on last edited by
      #2

      Does your QNetworkAccessManager emit encrypted() or sslErrors() signals? If so, what errors?

      1 Reply Last reply
      0

      • Login

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