Results 1 to 6 of 6

Thread: Posting images to AWS S3 with QNetworkAccessManager PUT (Android)

  1. #1

    Default Posting images to AWS S3 with QNetworkAccessManager PUT (Android)

    I am trying to get my android app (qt5 c++) to upload taken pictures to an amazon bucket using PUT method but keep getting errors about calculated signature not matching the one provided.

    here's my code:


    Qt Code:
    1. QFile * fileData = new QFile(path, this);
    2. if (fileData->open(QIODevice::ReadOnly))
    3. {
    4. QFileInfo fileInfo(fileData->fileName());
    5.  
    6. QByteArray AccessKey = "SOMEACCESKEY";
    7. QByteArray SecretKey = "SOMESECRETKEY";
    8. QByteArray DayOfWeek = QDateTime::currentDateTime().date().toString("ddd").toUtf8();
    9. QByteArray RFCDate = DayOfWeek + ", " + QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8();
    10. QByteArray S3Bucket = "somes3bucket";
    11. QByteArray S3region = "us-east-1";
    12. QByteArray ContentType = "image/jpeg";
    13. QByteArray StringToSign = "PUT\\n\\n" + ContentType + "\\n" + RFCDate + "\\n" + "/" + S3Bucket + "/" + fileInfo.fileName().toUtf8();
    14.  
    15. QByteArray SignString = QMessageAuthenticationCode::hash(StringToSign, SecretKey, QCryptographicHash::Sha1).toBase64();
    16.  
    17. QNetworkAccessManager * networkAccessManager = new QNetworkAccessManager(this);
    18.  
    19. QNetworkRequest request(QUrl("https://" + S3Bucket + ".s3." + S3region + ".amazonaws.com/" + fileInfo.fileName()));
    20. request.setHeader(QNetworkRequest::ContentTypeHeader, ContentType);
    21. request.setHeader(QNetworkRequest::ContentLengthHeader, fileInfo.size());
    22. request.setRawHeader("Host", S3Bucket + ".s3." + S3region + ".amazonaws.com");
    23. request.setRawHeader("Date", RFCDate);
    24. request.setRawHeader("Authorization", "AWS " + AccessKey + ":" + SignString);
    25.  
    26. m_reply = networkAccessManager->put(request, fileData);
    27. connect(m_reply, SIGNAL(finished()), this, SLOT(mySlot()));
    28. }
    To copy to clipboard, switch view to plain text mode 


    here's the error msg I am getting when reading m_reply->readAll():

    <Code>SignatureDoesNotMatch</?Code>
    <Message>The request signature we calculated does not match the signature you provided.? Check your key and signing method.?</?Message>


    any help is much appreciated!

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,266
    Thanks
    308
    Thanked 868 Times in 855 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Posting images to AWS S3 with QNetworkAccessManager PUT (Android)

    Do you have access to the signature stored with AWS? Is it in fact different from the one you are sending? Have you carefully checked your access code and secret keys to make sure there aren't any typos?

    Are there byte order (endian) differences between android architecture and the order expected by AWS (presumably internet byte order, big endian)? Take a look at QtEndian if so.
    Last edited by d_stranz; 10th January 2025 at 17:01.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3

    Default Re: Posting images to AWS S3 with QNetworkAccessManager PUT (Android)

    the error message provides <StringToSign> and <SignatureProvided> fields, I believe <StringToSign> is auto calculated based on the header parameters I send and it matches the one I build (StringToSign in the code), however when I use online hmac calculators (like https://dinochiesa.github.io/hmachash/index.html for example) and enter that string, my secret key and select sha1 function the base64 output doesn't match my signed string for some reason. does it mean that QMessageAuthenticationCode::hash(StringToSign, SecretKey, QCryptographicHash::Sha1).toBase64() doesn't work as expected?

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,266
    Thanks
    308
    Thanked 868 Times in 855 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Posting images to AWS S3 with QNetworkAccessManager PUT (Android)

    Network byte order is big-endian. Android is little-endian, so it is possible that your hash() call is generating a little-endian QByteArray. So try this:

    Qt Code:
    1. #include <QtEndian>
    2.  
    3. QByteArray AndroidTemp = QMessageAuthenticationCode::hash(StringToSign, SecretKey, QCryptographicHash::Sha1);
    4. QByteArray AndroidString = AndroidTemp.toBase64(); // for comparison purposes
    5.  
    6. QByteArray SignTemp( AndroidString ); // copy so the two arrays are the same size
    7. qToBigEndian( &AndroidTemp, AndroidTemp.size(), &SignTemp );
    8.  
    9. QByteArray SignString = SignTemp.toBase64();
    To copy to clipboard, switch view to plain text mode 

    Are SignString and AndroidString the same? If so, then hash() is generating a big-endian array. If not, then it is probably little-endian.
    Try sending this version of SignString to AWS
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  5. #5

    Default Re: Posting images to AWS S3 with QNetworkAccessManager PUT (Android)

    Quote Originally Posted by d_stranz View Post
    Network byte order is big-endian. Android is little-endian, so it is possible that your hash() call is generating a little-endian QByteArray. So try this:

    Qt Code:
    1. #include <QtEndian>
    2.  
    3. QByteArray AndroidTemp = QMessageAuthenticationCode::hash(StringToSign, SecretKey, QCryptographicHash::Sha1);
    4. QByteArray AndroidString = AndroidTemp.toBase64(); // for comparison purposes
    5.  
    6. QByteArray SignTemp( AndroidString ); // copy so the two arrays are the same size
    7. qToBigEndian( &AndroidTemp, AndroidTemp.size(), &SignTemp );
    8.  
    9. QByteArray SignString = SignTemp.toBase64();
    To copy to clipboard, switch view to plain text mode 

    Are SignString and AndroidString the same? If so, then hash() is generating a big-endian array. If not, then it is probably little-endian.
    Try sending this version of SignString to AWS
    thank you for your reply - turned out my issue with signature was caused by the double slashes in StringToSign so replacing \\n with \n solved it - I am not getting any more errors but m_reply->readAll() now returns an empty string, no errors are reported by errorOccurred signal and nothing gets posted to s3. so not sure what is wrong now

  6. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,266
    Thanks
    308
    Thanked 868 Times in 855 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Posting images to AWS S3 with QNetworkAccessManager PUT (Android)

    I am not getting any more errors but m_reply->readAll() now returns an empty string
    From what I read in the docs about QNetworkReply, the finished() signal is emitted after the put() request is completely done. So by the time you see that, all of the reply has been sent and there is nothing more to read.

    I think what you need to do is the handle the QIODevice::readyRead() signal and in your slot retrieve all of the pending data and put it onto the end of a buffer. Keep doing that until you receive the finished() signal, at which point you know you have received everything the server is going to send.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. how to use QNetworkAccessManager to download images in QT
    By iswaryasenthilkumar in forum Newbie
    Replies: 5
    Last Post: 6th March 2015, 10:54
  2. QNetworkAccessManager not receiving data in Android, but works in Desktop
    By kubark42 in forum Qt for Embedded and Mobile
    Replies: 5
    Last Post: 23rd November 2014, 18:19
  3. Http Posting using QNetworkAccessManager
    By Mohammadhzp in forum Newbie
    Replies: 17
    Last Post: 24th January 2014, 18:00
  4. Replies: 2
    Last Post: 8th January 2014, 16:40

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.