Subject: Azure Blob Storage – Issue with MAC Signature Mismatch in Block Blob Upload

I’m currently facing an issue with uploading block blobs to Azure Blob Storage using the REST API. I’m constructing the string-to-sign as per the Azure documentation, but I’m consistently receiving a 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. error.

$str2sign = "PUTnnn$blockSizenn$blockMimeTypennnnnnx-ms-blob-type:BlockBlobnx-ms-date:$Datenx-ms-version:2019-12-12n$headerResourcen$urlResource";

Where $headerResource is x-ms-blob-type:BlockBlobnx-ms-date:$Datenx-ms-version:2019-12-12 and $urlResource is /$storageAccountname/$containerName/$blobNamenblockid:" . urlencode($blockId) . "ncomp:block".

I’m then creating the signature as follows:

<?php
$sig = base64_encode(hash_hmac('sha256', urldecode(utf8_encode($str2sign)), base64_decode($accesskey), true));
?>

And the authorization header:

<?php
$authHeader = "SharedKey $storageAccountname:$sig";
?>

The headers for the request are set as follows:

<?php
$headers = [
  'Authorization: ' . $authHeader,
  'x-ms-date: ' . $Date,
  'x-ms-version: 2019-12-12',
  'Content-Length: ' . strlen($blockList),
  'Content-Type: application/xml',
];
?>

And the request is sent using curl:

<?php
curl_setopt($ch, CURLOPT_URL, $URL);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $blockList);

$result = curl_exec($ch);
?>

Despite following the documentation, I’m still facing this issue. I’ve also ensured that the Content-Length header is included in the string-to-sign if it is included in the request, and that the query parameters in the CanonicalizedResource part of the string-to-sign are in lexicographical order.

Interestingly, I have other functions for uploading and showing blobs that are working fine, which are using the same method for authentication. Here’s an excerpt from the show function:

<?php
// Azure Blob Storage download
$Date = gmdate('D, d M Y H:i:s GMT');

$headerResource = "x-ms-date:$Datenx-ms-version:2019-12-12";
$urlResource = "/$storageAccountname/$containerName/$blobName";

$arraysign = array();
$arraysign[] = 'GET';               /*HTTP Verb*/
$arraysign[] = '';                  /*Content-Encoding*/
$arraysign[] = '';                  /*Content-Language*/
$arraysign[] = '';                  /*Content-Length (include value when zero)*/
$arraysign[] = '';                  /*Content-MD5*/
$arraysign[] = '';                  /*Content-Type*/
$arraysign[] = '';                  /*Date*/
$arraysign[] = '';                  /*If-Modified-Since */
$arraysign[] = '';                  /*If-Match*/
$arraysign[] = '';                  /*If-None-Match*/
?>

I would appreciate any guidance or suggestions on what might be causing this issue and how to resolve it.

Thank you.