From 5a0b7d6746ccbcb59833b49a940162847fa4216a Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Tue, 11 Aug 2026 19:43:20 +0100 Subject: [PATCH] crypt: fix hash mismatches with no_data_encryption on backends which check upload hashes Before this change, when no_data_encryption was set, uploads from local disk advertised the hash of the encrypted data even though the data was uploaded unencrypted. On backends which check upload hashes (eg b2) this made uploads of small files fail with errors like "Checksum did not match data received", and made chunked uploads store an incorrect hash so the files failed their checksum on download with "corrupted on transfer: SHA1 hashes differ". See: https://forum.rclone.org/t/sha1-mismatches-on-b2-with-no-data-encryption-true/54121 --- backend/crypt/crypt.go | 5 +++++ backend/crypt/crypt_internal_test.go | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/backend/crypt/crypt.go b/backend/crypt/crypt.go index 1c02aaa7d..13f5f0246 100644 --- a/backend/crypt/crypt.go +++ b/backend/crypt/crypt.go @@ -1179,6 +1179,11 @@ func (o *ObjectInfo) Size() int64 { // Hash returns the selected checksum of the file // If no checksum is available it returns "" func (o *ObjectInfo) Hash(ctx context.Context, hash hash.Type) (string, error) { + // If the data is unchanged then the hash of the source is the + // hash of the object which will be uploaded + if o.f.opt.NoDataEncryption { + return o.ObjectInfo.Hash(ctx, hash) + } var srcObj fs.Object var ok bool // Get the underlying object if there is one diff --git a/backend/crypt/crypt_internal_test.go b/backend/crypt/crypt_internal_test.go index a6eaecbc5..8cf49a396 100644 --- a/backend/crypt/crypt_internal_test.go +++ b/backend/crypt/crypt_internal_test.go @@ -84,6 +84,10 @@ func testObjectInfo(t *testing.T, f *Fs, wrap bool) { // Test ObjectInfo.Hash wantHash := md5.Sum(outBuf.Bytes()) + if f.opt.NoDataEncryption { + // If the data isn't encrypted, the hash should be that of the plaintext + wantHash = md5.Sum([]byte(contents)) + } gotHash, err := src.Hash(ctx, hash.MD5) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("%x", wantHash), gotHash)