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. QT 5.15 QSSLCertificate::importpkcs12 returns false, how do I debug the reason?
Forum Updated to NodeBB v4.3 + New Features

QT 5.15 QSSLCertificate::importpkcs12 returns false, how do I debug the reason?

Scheduled Pinned Locked Moved Unsolved General and Desktop
14 Posts 4 Posters 1.5k Views 1 Watching
  • 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.
  • D Dadde

    @JonB I updated my post with the assert, it passes so the file is opened.

    D Offline
    D Offline
    Dadde
    wrote on last edited by
    #4

    @Dadde I still have the issue though that importPkcs12 function fails. Is there any way to know exactly what part of the function is failing? Is it because I pass pfxFile as a QFile when the input parameter is actually QIODevice, even though QFile is inheriting QIODevice and therefore seems to compile?

    Or is the password of the wrong type? Here's how I declare it in the related header:

    QByteArray certPassword = "mypassword";

    JonBJ 1 Reply Last reply
    0
    • D Dadde

      @Dadde I still have the issue though that importPkcs12 function fails. Is there any way to know exactly what part of the function is failing? Is it because I pass pfxFile as a QFile when the input parameter is actually QIODevice, even though QFile is inheriting QIODevice and therefore seems to compile?

      Or is the password of the wrong type? Here's how I declare it in the related header:

      QByteArray certPassword = "mypassword";

      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #5

      @Dadde said in QT 5.15 QSSLCertificate::importpkcs12 returns false, how do I debug the reason?:

      Is it because I pass pfxFile as a QFile when the input parameter is actually QIODevice, even though QFile is inheriting QIODevice and therefore seems to compile?

      No, that is fine.
      I do not have an answer to how you discover exactly what is wrong.

      1 Reply Last reply
      1
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by SGaist
        #6

        Hi,

        Which version of Qt are you using ?
        On which platform ?
        Would it be possible for you to share how one can generate such a certificate to test ?
        The Python code you are using as well so people can double check in conditions similar as yours.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        D 1 Reply Last reply
        1
        • C Offline
          C Offline
          ChrisW67
          wrote on last edited by
          #7

          Have you installed the relevant OpenSSL libraries into the runtime path of your executable?
          Have you provided the correct password for the input file?

          D 1 Reply Last reply
          1
          • SGaistS SGaist

            Hi,

            Which version of Qt are you using ?
            On which platform ?
            Would it be possible for you to share how one can generate such a certificate to test ?
            The Python code you are using as well so people can double check in conditions similar as yours.

            D Offline
            D Offline
            Dadde
            wrote on last edited by Dadde
            #8

            @SGaist I'm using QT version 5.15.2, visual studio

            I don't know myself how to create the certificate since I'm new to these topics but I will see what I can accomplish after the weekend.

            I think I can provide the python code though:

            import base64
            import requests
            import jwt
            import hashlib
            import uuid
            from datetime import datetime, timedelta
            from cryptography.hazmat.backends import default_backend
            from cryptography.hazmat.primitives import hashes, serialization
            from cryptography.hazmat.primitives.serialization import pkcs12
             
            token_endpoint = 'https://xxx.yyy/zzz/oauth2/token'
             
            # ADFS endpoint URL
            authority = 'https://xxx.yyy/zzz'
             
            # PFX certificate file path and password
            cert_file = 'C:/xxx/yyy/zzz.pfx'
            cert_password = 'password'
             
            # Client ID and Secret for your registered application on ADFS
            client_id = 'xxx-yyy-zzz-vvv-www'
             
            # Define the scope of the access token
            scope = ['https://xxx.yyy.zzz.vvv']
             
            # Load the PFX certificate
            with open(cert_file, 'rb') as f:
                pfx_data = f.read()
             
            # Load the PFX data and extract the private key
            private_key, cert, ca_certs = pkcs12.load_key_and_certificates(pfx_data, cert_password.encode(), default_backend())
             
            def hex_string_readable(bytes):
                    return ["{:02X}".format(x) for x in bytes]
            fingerprint = hex_string_readable(cert.fingerprint(hashes.SHA1()))
            print(",".join(str(element) for element in fingerprint))
             
            # Serialize the private key to PEM format
            private_key_pem = private_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()
            )
            # Convert bytes to string
            private_key_pem_str = private_key_pem.decode()
             
            print(private_key_pem_str)
             
            # Create a client assertion
            now = datetime.utcnow()
            expiry = now + timedelta(minutes=10)  # Set expiry time for 10 minutes from now
             
            kid = "".join(str(element) for element in fingerprint)
             
            cert_sha1 = hashlib.sha1()
            cert_sha1.update(cert.public_bytes(serialization.Encoding.DER))
             
            # Convert the SHA-1 hash to base64
            x5t = base64.urlsafe_b64encode(cert_sha1.digest()).rstrip(b'=').decode()
             
            claims = {
                "aud": token_endpoint,
                "iss": client_id,
                "sub": client_id,
                "jti": str(uuid.uuid4()),
                "exp": expiry,
            }
             
            header = {
                "kid": kid,
                "x5t": x5t
            }
            # Encode and sign the JWT using the private key
            client_assertion_bytes = jwt.encode(claims, private_key_pem_str, algorithm='RS256', headers=header)
             
            # Prepare data for token request
            token_request_data = {
                'grant_type': 'client_credentials',
                'client_id': client_id,
                'scope': scope,
                'client_assertion_type': 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
                'client_assertion': client_assertion_bytes,
            }
             
            # Send token request to ADFS token endpoint
            response = requests.post(token_endpoint, data=token_request_data)
             
            # Check if the token request was successful
            if response.status_code == 200:
                # Print the access token
                access_token = response.json()['access_token']
                print("Access token:", access_token)
            else:
                print("Failed to acquire token:", response.text)
             
            url = "https://xxx.yyy.zzz.vvv/v2/data.xml"
             
            payload = "Change to your request"
            headers = {
              'Content-Type': 'application/xml',
              'Authorization': 'Bearer '+access_token
            }
             
            response = requests.request("POST", url, headers=headers, data=payload)
             
            print(response.text)
            
            1 Reply Last reply
            0
            • C ChrisW67

              Have you installed the relevant OpenSSL libraries into the runtime path of your executable?
              Have you provided the correct password for the input file?

              D Offline
              D Offline
              Dadde
              wrote on last edited by Dadde
              #9

              @ChrisW67 My hope was that the QT framework has the tools I need to accomplish oauth2 communication(with certification) and it seems that it does, at least for this step with creating the pkcs12 file? Will I still need OpenSsl?

              D 1 Reply Last reply
              0
              • D Dadde

                @ChrisW67 My hope was that the QT framework has the tools I need to accomplish oauth2 communication(with certification) and it seems that it does, at least for this step with creating the pkcs12 file? Will I still need OpenSsl?

                D Offline
                D Offline
                Dadde
                wrote on last edited by
                #10

                @Dadde I did some reading and I think I already have openssl configured since I previously included QtNetwork which should contain these tools: https://doc.qt.io/qt-5/ssl.html

                JonBJ 1 Reply Last reply
                0
                • D Dadde

                  @Dadde I did some reading and I think I already have openssl configured since I previously included QtNetwork which should contain these tools: https://doc.qt.io/qt-5/ssl.html

                  JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by JonB
                  #11

                  @Dadde
                  I do not use SSL nor build Qt from source, so I could easily be incorrect here. But I think you have to do something/check that you do have OpenSSL installed and found from Qt app.

                  I think they come with OS or Qt binary installer or you download or build them yourself. @ChrisW67 asked you above

                  Have you installed the relevant OpenSSL libraries into the runtime path of your executable?

                  What OpenSSL libraries do you have where on what platform, and how is your program run such that it will locate and load them?

                  D 1 Reply Last reply
                  1
                  • JonBJ JonB

                    @Dadde
                    I do not use SSL nor build Qt from source, so I could easily be incorrect here. But I think you have to do something/check that you do have OpenSSL installed and found from Qt app.

                    I think they come with OS or Qt binary installer or you download or build them yourself. @ChrisW67 asked you above

                    Have you installed the relevant OpenSSL libraries into the runtime path of your executable?

                    What OpenSSL libraries do you have where on what platform, and how is your program run such that it will locate and load them?

                    D Offline
                    D Offline
                    Dadde
                    wrote on last edited by Dadde
                    #12

                    @JonB @ChrisW67 I haven't "explicitly" installed openssl, so I'm not 100% sure myself, but there is a QSslSocket::sllLibraryBuildVersionString() function that tells the openssl version found and used. I think it is fairly safe to say it is what is used for the QSslCertificate() function as well since it is part of the QTNetwork module which I have installed. I think it is the closest I can get to know if openssl is used?

                    Here's what the function says when I run it in my program: "OpenSSL 1.1.1g 21 Apr 2020".

                    I will update the code in the main post.

                    D 1 Reply Last reply
                    0
                    • D Dadde

                      @JonB @ChrisW67 I haven't "explicitly" installed openssl, so I'm not 100% sure myself, but there is a QSslSocket::sllLibraryBuildVersionString() function that tells the openssl version found and used. I think it is fairly safe to say it is what is used for the QSslCertificate() function as well since it is part of the QTNetwork module which I have installed. I think it is the closest I can get to know if openssl is used?

                      Here's what the function says when I run it in my program: "OpenSSL 1.1.1g 21 Apr 2020".

                      I will update the code in the main post.

                      D Offline
                      D Offline
                      Dadde
                      wrote on last edited by
                      #13

                      @Dadde Update: I added "Q_ASSERT(QSslSocket::supportsSsl());" and it returns false, so I guess I haven't actually properly implemented openssl then, also previous function "QSslSocket::sllLibraryBuildVersionString()" only checks what version it finds during compile time, "QSslSocket::sslLibraryVersionNumber();" is for runtime and it returns "0". I will look into implementing openssl properly and update if it solved my issue.

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

                        QSslSocket::sllLibraryBuildVersionString() "Returns the version string of the SSL library in use at compile time. " That is, the version of the OpenSSL libraries that the Qt binaries you are using were built to match. This does not mean those libraries are present in your runtime environment: they are detected and used if present.

                        So, your runtime environment needs to have OpenSSL 1.1.1 libraries. You may be able to access a compatible version through the Qt Online Installer. Ensuring it is in the run time environment (application binary directory or PATH on Windows, LD_LIBRARY_PATH on Linux etc.) is largely up to you.

                        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