Hi
I'm currently developing some stuff that requires me to upload blobs to the azure blob storage but I've been having some issue with the message signature. On most of my request it works and my table requests never fails (create table, update entity, insert
entity and delete entity). The issue start with azure returning the following error:
<?xml version="1.0" encoding="utf-8"?><Error><Code>InternalError</Code><Message>Server encountered an internal error. Please try again after some time.
RequestId:b3728784-8a0d-4fa9-95be-026b8c756a52
Time:2012-04-15T21:58:51.8698953Z</Message></Error>"
I then reuse the old request to do a retry. The old message signature looked like this:
"PUT
5506416
x-ms-blob-type:BlockBlob
x-ms-date:Sun, 15 Apr 2012 21:58:47 GMT
x-ms-meta-blobtype:Asset
x-ms-version:2009-09-19
/devstoreaccount1/devstoreaccount1/owner/WindowsAzureEmulator-x64.exe20120124000500000"
But then I get the following error message when retrying:
<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:da59b79c-fd3c-4003-acd2-9f0f6bdc9c64
Time:2012-04-15T21:58:52.3098953Z</Message><AuthenticationErrorDetail>The MAC signature found in the HTTP request 'YUo4shHIcNLnX3rVuNDsn3egE/YL2wGU6yWQ5YkC01Q=' is not the same as any computed signature. Server used following string to sign: 'PUT
0
x-ms-blob-type:BlockBlob
x-ms-date:Sun, 15 Apr 2012 21:58:47 GMT
x-ms-meta-blobtype:Asset
x-ms-version:2009-09-19
/devstoreaccount1/devstoreaccount1/owner/WindowsAzureEmulator-x64.exe20120124000500000'.</AuthenticationErrorDetail></Error>"
Now the content length is set to 0 for some reason and it doesnt work anymore. I am aware of that the request only works for 15 min, but this retry happens a few seconds after the first try. I'm not getting this error when retyring the table requests (for
example if the table doesn't exist), it's just for the blob storage I get this.
This is what the function that creates the header looks like:
QString AzureRestHandler::authorizationHeader(const QString& method, const QDateTime& now, const QNetworkRequest& request, const qint64 contentLength, const QString& ifMatch, const QString& md5) {
QString messageSignature = (isTableStorage() ?
QString("%1\n\n%2\n%3\n%4")
.arg(method,
"application/atom+xml",
QString("%1 GMT").arg(now.toString("ddd, dd MMM yyyy hh:mm:ss")).toUtf8().constData(),
canonicalizedResource(request.url()))
: QString("%1\n\n\n%2\n%3\n\n\n\n%4\n\n\n\n%5%6")
.arg(method,
(contentLength == 0 ? "" : QString::number(contentLength)),
md5,
ifMatch,
canonicalizedHeaders(request),
canonicalizedResource(request.url())));
qDebug() << "Message signature: " << messageSignature;
std::string decoded;
cryptlite::base64::decode(_storageKey.toStdString(), decoded);
boost::uint8_t digest[cryptlite::sha256::HASH_SIZE];
cryptlite::hmac<cryptlite::sha256>::calc(messageSignature.toStdString(), decoded, digest);
return QString("SharedKey %1:%2").arg(_storageAccount, QString::fromStdString(cryptlite::base64::encode_from_array(digest, cryptlite::sha256::HASH_SIZE)));
}
If you need anymore info to be able to help we I will happy to provide it. I really need some help with this one. Thank you