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. Converting cURL command and openSSL signing to Qt
Forum Updated to NodeBB v4.3 + New Features

Converting cURL command and openSSL signing to Qt

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 3 Posters 1.2k Views 3 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.
  • P Offline
    P Offline
    PrateekKhatri
    wrote on last edited by
    #1

    I currently use an HTTP PUT request using cURL and openSSL to upload files on S3 Bucket.
    Being new to Qt and not being familiar with Windows environment too much, I am pretty much stuck trying to figure out the best way to go about this.
    I have contemplated on installing cURL, openSSL, date, base64 etc. on Windows environment and using Qt to invoke command line, but that involves a lot of dependencies with my application. It would be really great to use Qt framework to be able to request this successfully.

    Here is the shell script I had been using on the Linux Environment:

    #!/bin/bash
    
    fileName=$1
    AccessKey="EXAMPLEACCESSKEY"
    SecretKey="mysecretkey"
    RFCDate=`date -R`
    S3Bucket="my-bucket"
    S3Path="/${S3Bucket}/${fileName}"
    ContentType="application/octet-stream"
    StringToSign="PUT\\n\\n${ContentType}\\n${RFCDate}\\n${S3Path}"
    SignString=`echo -en ${StringToSign} | openssl sha1 -hmac ${SecretKey} -binary
    | base64`
    curl -X PUT -T "${fileName}" \
    -H "Host: ${S3Bucket}.s3.amazonaws.com" \
    -H "Date: ${RFCDate}" \
    -H "Content-Type: ${ContentType}" \
    -H "Authorization: AWS ${AccessKey}:${SignString}" \
    http://${S3Bucket}.s3.amazonaws.com/${fileName}
    

    Please advise on how to go about converting this to Qt framework.

    Thanks!

    1 Reply Last reply
    0
    • Pablo J. RoginaP Offline
      Pablo J. RoginaP Offline
      Pablo J. Rogina
      wrote on last edited by
      #2

      @PrateekKhatri you may want to take a look at QNetworkAccessManager::put() method.

      Upvote the answer(s) that helped you solve the issue
      Use "Topic Tools" button to mark your post as Solved
      Add screenshots via postimage.org
      Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

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

        Hi,

        You'll need at least OpenSSL for the encryption part. The rest you can do with QNetworkAccessManager as @Pablo-J-Rogina suggests. Base64 is already supported by QByteArray.

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

        P 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          You'll need at least OpenSSL for the encryption part. The rest you can do with QNetworkAccessManager as @Pablo-J-Rogina suggests. Base64 is already supported by QByteArray.

          P Offline
          P Offline
          PrateekKhatri
          wrote on last edited by
          #4

          @SGaist

          void LogMgr::startLogUpload()
          {
              QNetworkAccessManager networkAccessManager;
          
              QByteArray RFCDate = QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8();
              QByteArray S3Path = "/" + m_S3Bucket + "/" + m_logFileName.toUtf8();
              QByteArray StringToSign = "PUT\n\n" + m_ContentType + "\n" + RFCDate + "\n" + S3Path;
              QByteArray SignString = QMessageAuthenticationCode::hash(StringToSign,
                                                                       m_SecretKey, QCryptographicHash::Sha1).toBase64();
          
              QNetworkRequest request(QUrl(m_S3Bucket + ".s3.amazonaws.com/" + m_logFileName));
              request.setRawHeader("Host", m_S3Bucket + ".s3.amazonaws.com");
              request.setRawHeader("Date", RFCDate);
              request.setHeader(QNetworkRequest::ContentTypeHeader, m_ContentType);
              request.setRawHeader("Authorization", "AWS " + m_AccessKey + ":" + SignString);
          
              QFile file(m_logFileName);
          
              qDebug() << "Sending Request";
              m_networkReply = networkAccessManager.put(request, &file);
              connect(m_networkReply, &QNetworkReply::finished, this, &LogMgr::fileUploadResponseCheck);
          
              qDebug() << m_networkReply->errorString();
              qDebug() << m_networkReply->error();
          }
          
          void LogMgr::fileUploadResponseCheck()
          {
              disconnect(m_networkReply, &QNetworkReply::finished, this, &LogMgr::fileUploadResponseCheck);
              qDebug() << "Are we ever here??";
              QList<QByteArray> headerList = m_networkReply->rawHeaderList();
          
              for (quint8 i = 0; i < headerList.length(); ++i)
              {
                  qDebug() << m_networkReply->rawHeader(headerList[i]);
              }
          
          }
          

          This is what I could currently have. However, I am seeing Unknown Error as output for errorString() and QNetworkReply::NetworkError(NoError) as output for error().
          Also, the slot for finished() signal is never being called.

          How do I exactly get OpenSSL to work with Qt, and how would I use it in this case?

          1 Reply Last reply
          0
          • P Offline
            P Offline
            PrateekKhatri
            wrote on last edited by PrateekKhatri
            #5

            Update:

            After a lot of reading and trial and error, I've reached to a point where I do get a response from the S3 server and the finished signal emits.

            Here is the Code I have now:

            void LogMgr::startLogUpload()
            {
                QNetworkAccessManager * networkAccessManager;
                networkAccessManager = new QNetworkAccessManager(this);
                connect(networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(fileUploadResponseCheck(QNetworkReply*)));
            
                QByteArray RFCDate = QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8();
                qDebug() << RFCDate;
                QByteArray S3Path = "/" + m_S3Bucket + "/" + m_logFileName.toUtf8();
                QByteArray StringToSign = "PUT\n\n" + m_ContentType + "\n" + RFCDate + "\n" + S3Path;
                QByteArray SignString = QMessageAuthenticationCode::hash(StringToSign,
                                                                         m_SecretKey, QCryptographicHash::Sha1).toBase64();
            
                QNetworkRequest request(QUrl("http://" + m_S3Bucket + ".s3.amazonaws.com/" + m_logFileName));
                request.setRawHeader("Host", m_S3Bucket + ".s3.amazonaws.com");
                request.setRawHeader("Date", RFCDate);
                request.setHeader(QNetworkRequest::ContentTypeHeader, m_ContentType);
                request.setRawHeader("Authorization", "AWS " + m_AccessKey + ":" + SignString);
            
                QIODevice * fileData = new QFile(m_logFileName, this);
                if (fileData->open(QIODevice::ReadOnly))
                {
                    qDebug() << "Sending Request";
                    networkAccessManager->put(request, fileData);
                }
            }
            
            void LogMgr::fileUploadResponseCheck(QNetworkReply * reply)
            {
                qDebug() << "File Upload Response Check";
                if (reply == nullptr)
                {
                    qDebug() << "Network reply ptr empty";
                    return;
                }
                qDebug() << "Response " << reply->readAll();
            }
            

            I have never used AWS S3 before so I am unaware of this response error:

            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>AccessDenied</Code><Message>AWS authentication requires a valid Date or x-amz-date header</Message><RequestId>C9EDED0BEC1D699F</RequestId><HostId>ivgJ79t3rydmrW9Eeh8j1osjPlNKXgVHRIQeZ40iivrq4yZTb/u0c2yETZ0YGhGsDTW/0w2HZv0=</HostId></Error>"
            

            AWS Authentication requires a valid Date or x-amz-date header
            Surely this has something to do with the RFCDate header!

            Any advise on this would be really helpful.

            Edit:
            I found that the shell script returns date: Mon, 30 Apr 2018 18:35:18 -0700
            Qt RFC2822Date is returned as: "30 Apr 2018 18:28:23 -0700

            Going to try fixing this and will try again.

            Thanks,
            Prateek

            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