使用總和檢查碼驗證資料及偵測變更

為驗證資料完整性及偵測變更,Cloud Storage 建議您在 bucket 之間傳輸資料時使用檢查碼。本頁面說明 Cloud Storage 如何使用檢查碼,以及傳送要求時如何指定檢查碼。

使用檢查碼防止資料損毀

有時,資料在傳輸至雲端或從雲端傳輸時可能會損毀,原因包括軟體或硬體錯誤、記憶體或路由器錯誤、電力干擾,或是在長時間上傳檔案期間變更來源資料。

為協助您防範資料毀損,Cloud Storage 支援使用 CRC32C 和 MD5 檢查碼,驗證資料完整性並偵測資料變更。

建議使用 CRC32C 驗證方法執行完整性檢查。 系統支援使用 MD5 雜湊值驗證單一檔案上傳作業,但不支援以區塊上傳的物件,例如複合物件,以及使用 XML API 多部分上傳作業上傳的物件。

資料寫入的總和檢查碼

如果是物件寫入作業,用戶端會計算本機檔案的總和檢查碼,並附加至物件上傳要求的 HTTP 標頭。伺服器會接收資料酬載、計算自己的檢查碼,並在上傳完成後比較兩個檢查碼,驗證資料。如果總和檢查碼相符,物件就會連同總和檢查碼一併儲存在 Cloud Storage 中。如果總和檢查碼不符,寫入要求就會遭到拒絕,並傳回 BadRequestException: 400 錯誤。

資料寫入的伺服器端驗證

在下列情況下,Cloud Storage 會執行伺服器端驗證:

  • 在物件上傳要求中提供物件的 MD5 或 CRC32C 雜湊值。 如要瞭解物件上傳類型,請參閱「物件上傳」。

  • 在 Cloud Storage 中執行複製或重寫要求時。對於物件複製和重寫要求,Cloud Storage 會根據與來源物件一併儲存的不可編輯的檢查碼,自動執行伺服器端驗證。

JSON API 單一要求 (媒體) 上傳

如果是 JSON API 媒體上傳作業,您可以在要求的 X-Goog-Hash 標頭中指定總和檢查碼。例如:

curl -X POST --data-binary @Desktop/dog-pic.jpeg \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: image/jpeg" \
    -H "X-Goog-Hash: crc32c=n03x6A==" \
    "https://storage.googleapis.com/upload/storage/v1/b/my-bucket/o?uploadType=media&name=dog-pic.jpeg"

JSON API 多部分上傳

如果是 JSON API 多部分上傳,您可以在要求容器中指定檢查碼,無論是在物件中繼資料部分,還是第三個界線字串下方都可以。如要瞭解物件的 JSON 結構和有效鍵,請參閱「物件資源表示法」。

以下範例會在要求容器的物件中繼資料部分指定 CRC32C 檢查碼:

--separator_string
Content-Type: application/json; charset=UTF-8

{
"name":"my-document.txt",
"crc32c": "n03x6A=="
}

--separator_string
Content-Type: text/plain

This is a text file.
--separator_string--

以下範例會在要求容器的第三個界線字串中指定 CRC32C 總和檢查碼:

--separator_string
Content-Type: application/json; charset=UTF-8

{
"name":"my-document.txt"
}

--separator_string
Content-Type: text/plain

This is a text file.

--separator_string
Content-Type: application/json; charset=UTF-8

{ "crc32c": "n03x6A==" }
--separator_string--

JSON API 可繼續上傳

如果是 JSON API 可恢復上傳作業,您可以在完成上傳作業的最終要求 X-Goog-Hash 標頭中指定檢查碼。例如:

curl -i -X PUT --data-binary @Desktop/dog-pic.jpeg \
      -H "Content-Length: 2000000" \
      -H "X-Goog-Hash: crc32c=n03x6A==" \
      "SESSION_URI"

最終要求中指定的檢查碼是根據整個物件計算而來, 而不只是最終要求中的物件資料。

XML API 單次要求上傳

如果是 XML API 單一要求上傳,您可以在要求的 x-goog-hash 標頭中指定總和檢查碼。

例如:

curl -X PUT --data-binary @Desktop/dog-pic.jpeg \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: image/jpeg" \
    -H "x-goog-hash: crc32c=n03x6A==" \
    "https://storage.googleapis.com/my-bucket/dog-pic.jpeg"

XML API 單一要求上傳作業也接受標準 HTTP Content-MD5 標頭。詳情請參閱「Content-MD5 規格」。

XML API 多部分上傳作業

如果是 XML API 多部分上傳,您可以為每個上傳部分指定檢查碼。如要為上傳部分指定個別的總和檢查碼,請在該部分的請求中加入 x-goog-hash 標頭。

例如:

PUT /dog-pic.jpeg?partNumber=1&uploadId=ABgVH8 HTTP/1.1
Host: my-bucket.storage.googleapis.com
Content-Length: 1000000
x-goog-hash: crc32c=n03x6A==

只有 CRC32C 檢查碼可用於驗證 XML API 多部分上傳的完整性。系統不支援 MD5 總和檢查碼。

gRPC 上傳

使用 gRPC 上傳物件時,您可以在任何上傳要求的第一個或最後一個 WriteObject 訊息中,指定物件層級的檢查碼,無論是單次上傳或支援續傳的上傳作業都適用。

此外,gRPC 也支援訊息層級的檢查碼。每個 WriteObject 訊息最多可包含 2 MiB 的資料區塊,每個區塊可包含自己的總和檢查碼。您可以指定訊息層級的總和檢查碼,取代或搭配物件層級的總和檢查碼。

平行複合上傳

如果是平行複合上傳,您應對每個元件上傳作業執行完整性檢查,然後使用上傳組合要求中的前提條件,防止發生競爭情況。撰寫要求不會進行伺服器端驗證,因此如要進行端對端完整性檢查,請對新的複合物件執行用戶端驗證。

Google Cloud CLI 複製及重寫

在 gcloud CLI 中,系統會自動驗證複製到 Cloud Storage bucket 或從該 bucket 複製的資料。對於 cp、mv 和 rsync 指令,gcloud CLI 會使用 MD5 或 CRC32C 總和檢查碼,判斷來源和目的地物件版本之間是否有差異。如果來源資料的總和檢查碼與目的地資料的總和檢查碼不符,gcloud CLI 會刪除無效副本並列印警告訊息。但這種情況極少發生。如果發生這種情況,請重新執行作業。

物件完成後,系統會自動進行驗證,無效物件會顯示 1 到 3 秒,隨後就會遭到識別並刪除。此外,gcloud CLI 可能會在上傳完成後中斷,但會在執行驗證前中斷,導致無效物件留在原處。如要避免這些問題,請使用 --content-md5 旗標指定 MD5 雜湊,在將單一檔案上傳至 Cloud Storage 時進行伺服器端驗證。

如果物件沒有 MD5 雜湊值,Google Cloud CLI 會忽略 --content-md5 旗標。

偵測「rsync」的變化

gcloud storage rsync 指令會在下列情況中比較總和檢查碼,判斷是否要略過轉移作業:

  • 來源和目的地都是 Cloud Storage bucket,且物件在兩個 bucket 中都有 MD5 或 CRC32C 檢查碼。

  • 物件在來源或目的地中都沒有檔案修改時間 (mtime)。

如果物件在來源和目的地都有 mtime 值 (例如來源和目的地都是檔案系統),rsync 指令會比較物件的大小和 mtime 值,而不是使用總和檢查碼。同樣地,如果來源是 bucket,目的地是本機檔案系統,rsync 指令會使用來源物件的建立時間做為 mtime 的替代值,且不會使用總和檢查碼。

如果 mtime 和總和檢查碼皆無法使用,rsync 只會比較檔案大小,判斷物件的來源版本和目的地版本之間是否有差異。舉例來說,比較複合物件與不支援 CRC32C 的雲端服務供應商物件時,由於複合物件沒有 MD5 總和檢查碼,因此無法使用 mtime 或總和檢查碼。

資料寫入的用戶端驗證

您可以發出上傳物件中繼資料的要求、比較上傳物件的雜湊值與預期值,並在不符時刪除物件,藉此對上傳內容執行用戶端驗證。如果上傳開始時不知道物件的 MD5 或 CRC32C 雜湊值,這個方法就很有用。

下表列出支援物件寫入檢查碼的各 Cloud Storage 用戶端最低版本。

客戶 支援物件寫入檢查碼的版本
Cloud Storage C++ 用戶端程式庫 2.46 以上版本
Cloud Storage Go 用戶端程式庫 1.60.0 以上版本
Cloud Storage Java 用戶端程式庫 2.62 以上版本
Cloud Storage Node.js 用戶端程式庫 7.19.0 以上版本
Cloud Storage PHP 用戶端程式庫 1.51.0 以上版本
Cloud Storage Python 用戶端程式庫 3.7.0 以上版本
Cloud Storage Ruby 用戶端程式庫 1.60.0
Cloud Storage .NET 用戶端程式庫 2.3.0 以上版本。建議使用 4.15.0,這個版本提供伺服器端檢查碼驗證。
Cloud Storage 連接器
  • 3.0.x Cloud Storage 連接器的 3.0.18 以上版本
  • 3.1.x Cloud Storage 連接器的 3.1.14 以上版本
  • 4.0.3 以上版本,適用於 4.0.x 版 Cloud Storage 連接器
Cloud Storage FUSE 3.8.0 以上版本
Google Cloud CLI

資料讀取和下載的總和檢查碼

如果是物件讀取和下載作業,伺服器會在回應中傳送物件及其儲存的檢查碼。用戶端會根據收到的位元組,計算讀取或下載檔案的自身檢查碼,並比較這兩個檢查碼,以驗證資料完整性。

讀取和下載作業的用戶端驗證

根據預設,所有 Cloud Storage 用戶端程式庫 SDK 都支援計算物件下載和讀取作業的總和檢查碼。下表提供各用戶端程式庫 SDK 的資訊,說明如何停用物件下載或讀取檢查碼。

用戶端程式庫 如何停用物件讀取或下載的總和檢查碼
Cloud Storage C++ 用戶端程式庫 在 C++ 用戶端程式庫中,您可以將 DownloadChecksumValidationOption 設為 ChecksumAlgorithm::kNone 值,停用檢查碼驗證。
Cloud Storage Go 用戶端程式庫 在 Go 用戶端程式庫中,您可以在初始化時提供讀取器選項,藉此停用檢查碼驗證。呼叫 NewReader 時傳遞 WithDisableReaderChecksum(),或呼叫 NewMultiRangeDownloader 時傳遞 WithDisableMRDReadChecksum()。
Cloud Storage Java 用戶端程式庫 如要在 Java 用戶端程式庫的讀取路徑上停用內部 CRC32C 檢查碼驗證,請傳遞 JVM 系統屬性 -Dcom.google.cloud.storage.Hasher.read=disabled,這會關閉讀取作業的內部雜湊器。如要全面停用讀取和寫入作業的檢查碼,請改用 -Dcom.google.cloud.storage.Hasher.default=disabled。
Cloud Storage Node.js 用戶端程式庫 在 Node.js 用戶端程式庫中,您可以在提供給下載方法呼叫的設定選項物件中傳遞 { validation: false },藉此停用檢查碼驗證。
Cloud Storage PHP 用戶端程式庫 在 PHP 用戶端程式庫中,您可以在呼叫下載方法時,將 'validate' => false 或 'validate' => 'none' 傳遞至關聯選項陣列 ($options['validate']) 內,藉此停用 JSON 和 XML API 讀取路徑的總和檢查碼驗證。
Cloud Storage Python 用戶端程式庫 在 Python 用戶端程式庫中,停用檢查碼驗證取決於用戶端傳輸:如果是 JSON 用戶端,請傳遞 checksum=None (方法中支援,例如 download_to_file),如果是 gRPC 用戶端,請設定 enable_checksum=False。
Cloud Storage Ruby 用戶端程式庫 在 Ruby 用戶端程式庫中,您可以將關鍵字引數 (checksum: 或 verify:) 直接傳遞至下載方法,並明確設定 verify: none 或 verify: false,即可停用總和檢查碼驗證。
Cloud Storage .NET 用戶端程式庫 在 .NET 用戶端程式庫中,您可以在傳遞至下載方法呼叫的 DownloadObjectOptions 物件上,將 ChecksumValidation 屬性設為 DownloadValidationMode.Never,即可停用檢查碼驗證。

對已下載或讀取的物件執行資料完整性檢查

在某些情況下,應用程式可能需要使用收到的位元組,獨立計算下載或讀取的檔案的總和檢查碼,並與伺服器提供的雜湊值進行比較,以驗證資料完整性。

如要對下載的資料執行完整性檢查,請在收到資料時計算檢查碼,並將結果與伺服器提供的檢查碼進行比較。

伺服器端檢查碼是以儲存在 Cloud Storage 中的完整物件為準,因此下列類型的下載作業無法根據伺服器提供的檢查碼進行驗證:

  • 經過解壓縮轉碼的下載內容:伺服器提供的檢查碼代表壓縮狀態的物件,而提供的資料已移除壓縮,因此檢查碼值不同。

  • 只包含部分物件資料的回應:這類回應適用於 Range 要求。

    gRPC 範圍讀取作業是這個項目的例外狀況,支援端對端驗證。在 gRPC 範圍讀取中,Cloud Storage 會在串流的每個個別回應區塊中加入專屬的 CRC32C 檢查碼,藉此驗證資料,讓用戶端立即驗證特定資料區塊在傳輸過程中是否損毀。如要進行更廣泛的驗證,串流也會提供整個物件的完整總和檢查碼,進階用戶端可用於計算滾動總計,並驗證較大檔案的完整性。

    如果應用程式需要讀取物件範圍,而非一次讀取完整物件,建議使用 gRPC。否則,建議您只使用範圍要求,在收到最後一個位移後重新啟動完整物件的下載作業,並在完整下載完成後計算及驗證總和檢查碼。

驗證下載內容時,如果計算出的檢查碼與伺服器提供的檢查碼不符,表示資料在傳輸過程中已損毀。在這些情況下,您應捨棄損毀的資料,並使用建議的重試邏輯重試要求。

後續步驟