How do I calculate an AWS S3 compatible SHA-256 hash from a Blob in Angular?

0

I am trying to upload an image from the client side (Angular app) using a presigned upload URL that is generated in the backend. When doing a PUT request to an Amazon S3 bucket using this presigned URL, a x-amz-content-sha256 signed header must be included with a valid SHA-256 value that is calculated from the image blob that will be uploaded using the presigned URL.

Currently I am calculating this SHA-256 hash using the following TypeScript code:

  private getSHA256ChecksumFromBlobAndCacheBoth(imageBlob: Blob): Promise<string> {
    return imageBlob.arrayBuffer()
      .then(arrayBuffer => crypto.subtle.digest("SHA-256", arrayBuffer))
      .then(arrayBuffer => { 
        let SHA256Checksum: string = this.convertSHA256ChecksumToHexString(arrayBuffer);
        return SHA256Checksum;
      });
  }
  
  private convertSHA256ChecksumToHexString(buffer: ArrayBuffer): string {
    return Array.from(new Uint8Array(buffer))
      .map((byte) => byte.toString(16).padStart(2, "0"))
      .join("");
  }

This produces a valid SHA-256 hash. Here's an example of one: ce48c8f1eebbfdfd811d2e8fbb07d7a4fa9e0ab382934d2010b336e2a2b41730

Despite it being valid, it is still rejected by S3; it causes a signature mismatch error. When I remove the actual hash value and replace it with UNSIGNED-PAYLOAD the upload request is accepted.

So Amazon calculates the SHA-256 of the same blob differently than how it's normally done.

How do I create an Amazon S3 compatible SHA-256 hash of an image blob in TypeScript/JavaScript?

asked 2 days ago20 views
1 Answer
0
Accepted Answer

It appears there may be a misunderstanding about how Amazon S3 handles SHA-256 checksums for presigned URLs. When using presigned URLs for S3 uploads, you typically don't need to calculate and include the SHA-256 hash of the content in the x-amz-content-sha256 header.

For presigned URLs, the x-amz-content-sha256 header is usually set to UNSIGNED-PAYLOAD by default. This is why your upload works when you use UNSIGNED-PAYLOAD instead of the calculated hash.

If you want to include a checksum for data integrity verification, S3 supports several checksum algorithms, including SHA-256. However, for this purpose, you would use a different header: x-amz-checksum-sha256.

To use the SHA-256 checksum with S3, you need to:

  1. Calculate the SHA-256 hash of your content.
  2. Base64 encode the resulting hash.
  3. Include this Base64 encoded hash in the x-amz-checksum-sha256 header.

Here's how you could modify your code to produce the correct format:

private async getSHA256ChecksumFromBlob(imageBlob: Blob): Promise<string> {
  const arrayBuffer = await imageBlob.arrayBuffer();
  const hashBuffer = await crypto.subtle.digest("SHA-256", arrayBuffer);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hashBase64 = btoa(String.fromCharCode.apply(null, hashArray));
  return hashBase64;
}

This function will return a Base64 encoded SHA-256 hash that you can use with the x-amz-checksum-sha256 header when uploading to S3.

Remember, when using presigned URLs, you typically don't need to include the content hash in the signature calculation. The presigned URL already contains the necessary signature. You would only include the x-amz-checksum-sha256 header if you want S3 to perform an additional integrity check on the uploaded data.

If you're still encountering issues, make sure that your backend is correctly generating the presigned URL and that you're including all the necessary headers in your upload request. You may also want to check if your S3 bucket or the specific operation requires any special configurations for checksums.
Sources
Introducing default data integrity protections for new objects in Amazon S3 | AWS News Blog
Amazon S3 Security Features - Amazon Web Services
S3 SHA256 Checksum for Presigned URL in File Upload | AWS re:Post

profile picture
answered 2 days ago
profile picture
EXPERT
reviewed 2 days ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions