moto icon indicating copy to clipboard operation
moto copied to clipboard

Multipart S3 uploads - composite checksums are not given the -X suffix

Open sophieilangolyon1-nhs opened this issue 8 months ago • 3 comments

As per the discussion referenced below, composite checksums when generated by AWS S3 are given an -X suffix to distinguish them from full object checksums. Moto does not do this, so composite checksums present as full object checksums which causes a problem when retrieving the object using botocore (which attempts to validate the checksum against a full object checksum, inevitably failing validation).

The attached python code can be run against AWS (with correct permissions) or against moto (with the 'mock' argument) to demonstrate the difference of behaviour. Note the two ExtraArgs options at line 27/28 which can be used to direct AWS towards composite or full object checksum generation.

reproduce-checksum-generation-problem.txt

Originally posted by @sophieilangolyon1-nhs in https://github.com/getmoto/moto/discussions/8760

sophieilangolyon1-nhs avatar Apr 04 '25 15:04 sophieilangolyon1-nhs

Hi @sophieilangolyon1-nhs, thanks for the detailed reproducer, and welcome to Moto! I'll mark it as a bug.

If this is something you want to work on yourself, PR's are always welcome! The documentation should have everything you need to get started: https://docs.getmoto.org/en/latest/docs/contributing/index.html

bblommers avatar Apr 06 '25 11:04 bblommers

Just to make this issue a bit more findable... The error I receive when attempting to read the object is similar to the following:

self = <botocore.httpchecksum.StreamingChecksumBody object at 0xffff9464bee0>

    def _validate_checksum(self):
        if self._checksum.digest() != base64.b64decode(self._expected):
            error_msg = (
                f"Expected checksum {self._expected} did not match calculated "
                f"checksum: {self._checksum.b64digest()}"
            )
>           raise FlexibleChecksumError(error_msg=error_msg)
E           botocore.exceptions.FlexibleChecksumError: Expected checksum TeqlgA== did not match calculated checksum: mhURAw==

To work around this, I'm using ChecksumMode="DISABLED" in my tests to avoid the error. For example:

content = s3_client.get_object(
    Bucket="test-bucket",
    Key="test-key1",
    ChecksumMode="DISABLED",
)["Body"].read()

mfulgo avatar May 01 '25 22:05 mfulgo

For Ref, I encountered the same issue when updating poetry dependencies in my package. I found that since Moto 5.1.2 my unittest are failing with the same type of msg

botocore.exceptions.FlexibleChecksumError: Expected checksum TeqlgA== did not match calculated checksum: mhURAw==

lbesnard avatar May 07 '25 02:05 lbesnard