esp_partition_get_sha256() mismatches PHP's hash() function in HTTPUpdate Disclaimer: It may be that this question belongs to a PHP forum instead of this one. However, this question is also very ESP32/Arduino related. Please correct me if this is the case.

The scenario:


Implementing self-update routines for my ESP32 project, using HTTPUpdate
Using a server-side PHP script to decide which binary image to serve to the device, or return HTTP 304 return code if no updates available.
Using the sketch's MD5 and SHA-256 hashes provided by the HTTPUpdate library as request headers, server-side, to check binary version.


The problem:


The MD5 hash contained in the request header "x-ESP32-sketch-md5" is the same as the MD5 hash calculated by a simple md5() call using the raw binary for the currently running version.
The SHA256 hash contained in the request header "x-ESP32-sketch-sha256" is not the same as the hash obtained by calling PHP's hash("sha256", $v) (where $v contains the same raw binary).


Example:


MD5 (HTTPUpdate): c93d814989b53a24a0164e561b6a8bf8
MD5 (PHP): c93d814989b53a24a0164e561b6a8bf8 (no difference)
SHA256 (HTTPUpdate): 5634674253E095600CD863A34287FCA742BCFCF9B5BF409870DD65AF0ADEF7A0
SHA256 (PHP): 1ECDDF3215520C79AAD13BBC1D116D9286910490DF316B9B203FCBFC89CBCCC2 (different)


Am I doing something wrong?

Note: The esp_partition_get_sha256() function is called internally by the update() method of the HTTPUpdate library.

PHP Code (for calculating the hashes):

&lt;?php

$v = file_get_contents("fw.bin");

print("MD5: ". md5($v)."\r\n");
print("SHA256: ".hash("sha256", $v)."\r\n");


Arduino code (the relevant part):

// Called once or twice a day
void update_fw()
{
    Serial.println("Checking for updates...");

    t_httpUpdate_return ret = httpUpdate.update(client, "http://my_server/fw/check_fw.php");  // For now it only logs the headers and returns HTTP 304 code

    switch (ret)
    {
      case HTTP_UPDATE_FAILED:
        Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str());
        break;

      case HTTP_UPDATE_NO_UPDATES:
        Serial.println("HTTP_UPDATE_NO_UPDATES");
        break;

      case HTTP_UPDATE_OK:
        Serial.println("HTTP_UPDATE_OK");
        break;
    }
}


PHP code (logs headers and returns HTTP 304 code):

&lt;?php

$headers = getallheaders();

if (!file_exists("log.txt"))
{
    file_put_contents("log.txt", print_r($headers, true));
}

http_response_code(304);            // No updates.

exit;


Thanks in advance.
Your problem stems from a misunderstanding of what the functions are doing.

Your MD5 hashes are the hash of the binary file itself. And so they match.

Your PHP SHA256 is the hash of the binary file (like the MD5), but the ESP's SHA256 is not.

The file itself contains an SHA256 hash of the content of the file, not the whole file.  The function esp_partition_get_sha256 merely returns that SHA256 hash.

According to the SDK documentation:


  For apps with SHA-256 appended to the app image, the result is the appended SHA-256 value for the app image content. The hash is verified before returning, if app content is invalid then the function returns ESP_ERR_IMAGE_INVALID. For apps without SHA-256 appended to the image, the result is the SHA-256 of all bytes in the app image. For other partition types, the result is the SHA-256 of the entire partition.


If you were to take the binary file and somehow strip off the extra sha256 information and then perform a hash of the results you should (theoretically) get the same hash, which would be the same has as is contained within the file itself.