Conversation
R2ChecksumAlgorithm is a closed set of the five digest algorithms R2 was
verified to enforce (probed against live R2, 2026-08-24): crc32, crc32c,
sha1, sha256, and md5. Each value carries its wire name, the header its
digest travels in (x-amz-checksum-{name}, or Content-MD5 for md5), its
exact digest byte length, and whether R2 accepts it on multipart part
uploads. UploadChecksum pairs an algorithm with a base64 digest and
validates at construction that the digest decodes to exactly the
algorithm's digest length; TryCreate validates untrusted algorithm and
digest strings without exceptions.
PresignedPutRequest and PresignedUploadPartRequest take an optional
Checksum, and PresignedUploadPartsRequest takes optional per-part
checksums keyed by part number. The client signs the digest header into
the URL, so the upload fails with 400 BadDigest and stores nothing when
the arriving bytes do not hash to the stated digest. On a collision with
the same header in HeadersToSign, the typed checksum wins.
R2 answers 501 NotImplemented to any part upload carrying a sha1 or
sha256 checksum header, regardless of the digest, so the part URL
methods refuse those two algorithms with ArgumentException before
signing. The batch generator also rejects a checksum keyed to a part
number absent from PartNumberAndLength, and now builds a fresh
GetPreSignedUrlRequest per part because the AWS SDK's HeadersCollection
cannot remove a header once set, which would leak one part's digest
header into later parts' URLs.
Integration tests pin the live matrix: every algorithm accepted with a
correct digest and rejected with a wrong one, on single-part PUTs (all
five) and part uploads (crc32, crc32c, md5), plus a batch multipart
upload with per-part digests completing end to end. The presigned GET
expiry test gets a wider validity window so the pre-expiry fetch cannot
race the window closing under parallel suite load. Version 2.3.0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
R2ChecksumAlgorithm is a closed set of the five digest algorithms R2 was verified to enforce (probed against live R2, 2026-08-24): crc32, crc32c, sha1, sha256, and md5. Each value carries its wire name, the header its digest travels in (x-amz-checksum-{name}, or Content-MD5 for md5), its exact digest byte length, and whether R2 accepts it on multipart part uploads. UploadChecksum pairs an algorithm with a base64 digest and validates at construction that the digest decodes to exactly the algorithm's digest length; TryCreate validates untrusted algorithm and digest strings without exceptions.
PresignedPutRequest and PresignedUploadPartRequest take an optional Checksum, and PresignedUploadPartsRequest takes optional per-part checksums keyed by part number. The client signs the digest header into the URL, so the upload fails with 400 BadDigest and stores nothing when the arriving bytes do not hash to the stated digest. On a collision with the same header in HeadersToSign, the typed checksum wins.
R2 answers 501 NotImplemented to any part upload carrying a sha1 or sha256 checksum header, regardless of the digest, so the part URL methods refuse those two algorithms with ArgumentException before signing. The batch generator also rejects a checksum keyed to a part number absent from PartNumberAndLength, and now builds a fresh GetPreSignedUrlRequest per part because the AWS SDK's HeadersCollection cannot remove a header once set, which would leak one part's digest header into later parts' URLs.
Integration tests pin the live matrix: every algorithm accepted with a correct digest and rejected with a wrong one, on single-part PUTs (all five) and part uploads (crc32, crc32c, md5), plus a batch multipart upload with per-part digests completing end to end. The presigned GET expiry test gets a wider validity window so the pre-expiry fetch cannot race the window closing under parallel suite load. Version 2.3.0.