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

為驗證資料完整性及偵測變更,Cloud Storage 建議您在傳入及傳出值區的資料時使用總和檢查碼。本頁說明 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 多部分上傳作業,您可以為整個物件指定 CRC32C 總和檢查碼,也可以為每個上傳部分指定個別的總和檢查碼。如要為上傳部分指定個別的總和檢查碼,請在該部分的請求中加入 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 值區的資料。對於 cpmvrsync 指令,gcloud CLI 會使用 MD5 或 CRC32C 總和檢查碼,判斷來源和目的地物件版本之間是否有差異。如果來源資料的檢查碼與目的地資料的檢查碼不符,gcloud CLI 會刪除無效副本並輸出警告訊息。但這種情況極少發生。萬一發生了,您可以再試一次。

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

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

變更「rsync」的偵測設定

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

  • 來源和目的地都是 Cloud Storage 值區,且物件在這兩個值區中都有 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 連接器
  • 3.0.x Cloud Storage 連接器的 3.0.18 以上版本
  • 3.1.14 以上版本 (適用於 3.1.x Cloud Storage 連接器)
  • 4.0.x Cloud Storage 連接器適用的 4.0.3 以上版本
Cloud Storage FUSE 3.8.0 以上版本
Google Cloud CLI

資料讀取作業的總和檢查碼

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

部分用戶端程式庫不會自動對下載的物件執行總和檢查碼驗證。應用程式可能需要使用收到的位元組,獨立計算下載檔案的總和檢查碼,並與伺服器提供的雜湊進行比較,以驗證資料完整性。

讀取作業的用戶端驗證

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

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

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

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

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

    如果應用程式需要讀取物件範圍,而不是一次讀取完整物件,建議使用 gRPC。否則,我們建議您只針對上次收到偏移之後重新啟動下載完整物件的情況使用範圍要求,因為這樣您才可以在整個下載作業完成時計算和驗證總和檢查碼。

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

後續步驟