Describe the feature
Make the S3Client GetObject API with ChecksumMode.ENABLED flag interpret the checksum field in the GetObjectResponse correctly.
Use Case
Currently, when we use GetObjectRequest.builder().range(...).checksumMode(ChecksumMode.ENABLED), the behavior is confusing.
Suppose we have an object uploaded via Multipart Upload, using S3 Part Level Additional Checksums. The S3Client treats the checksum returned from S3 as if it were checksum(object). In reality, that checksum is a checksum(checksum of each part). Using a get without the range() field set, the checksum returned will be of the format <checksum(checksum of each part)>-<partCount>. When using range(), the checksum from S3 is <checksum(checksum of each part)>. ChecksumValidatingInputStream compares checksum(object) against checksum(checksum of each part), which will not match. This can be confusing for users who then think either the checksum is stored incorrectly in S3 or the object bytes are wrong, when actually the problem is in how the SDK is interpreting checksums.
Proposed Solution
Prevent the SDK from attempting validations in cases where the object wasn't uploaded via the single part PutObject API. We can tell whether the object is multipart by looking at the etag or additional checksum returned from S3. The format of the etag or additional checksum will be suffixed with -<partCount>, so it should be possible to figure out the cases where it cannot treat the checksum as if it were a checksum(object). The main drawback to this is it may trick users into thinking the SDK did built-in validation when it actually didn't. I don't think it's possible to do the checksum(checksum of each part) validation without knowing the part size.
Other Information
Alternative 1: Don't allow the range() argument to be used alongside ChecksumMode.ENABLED. Similar to proposal, but explicitly notifies that validation won't happen and disallows the call altogether. I suppose it should be possible to validate single part uploaded objects in that case as long as we can tell the full object size. Maybe a worse user experience to do it this way and may break some implementations that already have these two parameters used together.
Alternative 2: We could make the SDK able to understand the different checksum cases and validate accordingly. This may be trickier (or impossible) to implement as there are more cases of validation to consider and the client wouldn't be able to tell part sizes. It would be nicer for users to get validation for free in as many cases as possible.
Acknowledgements
AWS Java SDK version used
2.26.23
JDK version used
17
Operating System and version
Amazon Linux 2
Describe the feature
Make the S3Client GetObject API with
ChecksumMode.ENABLEDflag interpret the checksum field in the GetObjectResponse correctly.Use Case
Currently, when we use GetObjectRequest.builder().range(...).checksumMode(ChecksumMode.ENABLED), the behavior is confusing.
Suppose we have an object uploaded via Multipart Upload, using S3 Part Level Additional Checksums. The S3Client treats the checksum returned from S3 as if it were checksum(object). In reality, that checksum is a checksum(checksum of each part). Using a get without the range() field set, the checksum returned will be of the format
<checksum(checksum of each part)>-<partCount>. When usingrange(), the checksum from S3 is<checksum(checksum of each part)>. ChecksumValidatingInputStream compareschecksum(object)againstchecksum(checksum of each part), which will not match. This can be confusing for users who then think either the checksum is stored incorrectly in S3 or the object bytes are wrong, when actually the problem is in how the SDK is interpreting checksums.Proposed Solution
Prevent the SDK from attempting validations in cases where the object wasn't uploaded via the single part PutObject API. We can tell whether the object is multipart by looking at the etag or additional checksum returned from S3. The format of the etag or additional checksum will be suffixed with
-<partCount>, so it should be possible to figure out the cases where it cannot treat the checksum as if it were achecksum(object). The main drawback to this is it may trick users into thinking the SDK did built-in validation when it actually didn't. I don't think it's possible to do thechecksum(checksum of each part)validation without knowing the part size.Other Information
Alternative 1: Don't allow the range() argument to be used alongside ChecksumMode.ENABLED. Similar to proposal, but explicitly notifies that validation won't happen and disallows the call altogether. I suppose it should be possible to validate single part uploaded objects in that case as long as we can tell the full object size. Maybe a worse user experience to do it this way and may break some implementations that already have these two parameters used together.
Alternative 2: We could make the SDK able to understand the different checksum cases and validate accordingly. This may be trickier (or impossible) to implement as there are more cases of validation to consider and the client wouldn't be able to tell part sizes. It would be nicer for users to get validation for free in as many cases as possible.
Acknowledgements
AWS Java SDK version used
2.26.23
JDK version used
17
Operating System and version
Amazon Linux 2