Object Storage Service (OSS) の ETag 値は、オブジェクトの内容が変更されたかどうかを識別するものであり、必ずしもそのオブジェクトの MD5 ハッシュと一致するわけではありません。データ整合性の検証には、ETag 値を使用しないでください。
Content-MD5 を用いたアップロード整合性の確認
アップロードしたオブジェクトがご利用のローカルファイルと一致することを確認するには、アップロードリクエストに Content-MD5 ヘッダーを含めてください。OSS は受信したオブジェクトの MD5 ハッシュを計算し、お客様が指定した Content-MD5 値と比較します。両者の値が一致した場合にのみ、アップロードは成功します。このヘッダーの指定は任意ですが、アップロードプロセスの一環としてデータ整合性を検証できます。
Content-MD5 ヘッダーは、署名計算に必ず含める必要があります。ヘッダーの値が署名と一致しない場合、OSS は SignatureDoesNotMatch エラーを返します。詳細については、「Authorization ヘッダーへの署名の含め方」をご参照ください。
Content-MD5 値の算出方法
Content-MD5 値は、リクエストボディのバイナリ形式の MD5 ダイジェストを Base64 エンコーディングしたものであり、16 進数文字列の Base64 エンコーディングではありません。
以下の例では、文字列 0123456789 を使用して、正しい算出方法と誤った算出方法を示します。
正しい算出方法
データの MD5 ハッシュを計算し、128 ビットのバイナリダイジェストを取得します。
そのバイナリダイジェストを Base64 エンコーディングします。
>>> import base64, hashlib
>>> hash = hashlib.md5()
>>> hash.update("0123456789") # Python 3 の場合:hash.update(b"0123456789")
>>> base64.b64encode(hash.digest())
'eB5eJF1ptWaXm4bijSPyxw=='hash.digest() は 128 ビットのバイナリダイジェストを返します:
>>> hash.digest()
'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7'誤った算出方法
よくある誤りとして、バイナリダイジェストではなく、32 文字の 16 進数文字列を Base64 エンコーディングしてしまうことがあります。これにより、不正な Content-MD5 値が生成されます。
# hash.hexdigest() は 32 文字の 16 進数文字列を返します — Content-MD5 の算出には使用しないでください。
>>> hash.hexdigest()
'781e5e245d69b566979b86e28d23f2c7'
# 16 進数文字列を Base64 エンコーディングすると、誤った結果になります:
>>> base64.b64encode(hash.hexdigest())
'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='