AWS S3のオブジェクトの ETag を MD5ハッシュにしたい

S3にアップロードされたファイルの同一性をチェックしたりするために、ハッシュ値を使いたく、 いろいろ調べたのでまとめます。

先に結論

ETagがMD5になる

ETagの値は、次の条件の場合 MD5ハッシュ が設定されます。

  • PUT、POST、またはCOPYで作成された、SSE-S3または平文で暗号化されたオブジェクト

ETagがMD5にならない

次の場合は MD5ハッシュにはなりません。

  • マルチパートアップロードでオブジェクトを作成した場合
  • 暗号化タイプが SSE-C または SSE-KMS の場合
  • 16MB以上のファイルを、AWSマネジメントコンソールで「コピー」->「貼り付け」した場合

マルチパートアップロードしたファイルの ETag にMD5を設定するには?

s3apiの CopyObject を実行するとよいです。

$ aws s3api copy-object --copy-source mybucket/myobject --bucket mybucket --key myobject --metadata-directive REPLACE --metadata a=b

ただし、単純な同一名での上書きはできず、次のいずれかの変更が必要となります。

(なので適当なa=bメタデータに設定してます。)

  • metadata
  • storage class
  • website redirect location
  • encryption attributes.

ちなみに上のコマンドをメタデータの変更をせずに実行すると...

$ aws s3api copy-object --copy-source mybucket/myobject --bucket mybucket --key myobject --metadata-directive REPLACE --metadata copied=true

An error occurred (InvalidRequest) when calling the CopyObject operation: This copy request is illegal because it is trying to copy an object to itself without changing the object's metadata, storage class, website redirect location or encryption attributes.

このようにエラーになります。

その他もろもろ

AWSマネジメントコンソール でのコピーの挙動

(2018-12 時点で) AWSマネジメントコンソールで「コピー」->「貼り付け」をした場合は、 CopyObject を実行せずに、16MBのパートに分割して内部でマルチパートアップロードしているようです。

16MBを超えるファイルは、コピー元のETagが MD5ハッシュ であっても、ETagの値がハイフン付きの値に変更されてしまいます。

aws-cli のファイルコピーについて

8MBを超えるファイルについては、8MBのパートに分割するようです。 つまり8MBを超えるファイルを s3 cp でアップロードしたらETagの値がハイフン付きの値になります。

これを避けるには、s3apiのPutObjectを使うとよいでしょう。

aws s3api put-object --bucket mybucket --key myobject --body myobject

マルチパートアップロード時のETagの値って??

公式な文書は見当たりませんが、次のように作成しているようです。

アップロードした各パートのMD5ハッシュを連結したもののMD5 + '-' + パート数

https://stackoverflow.com/questions/12186993/what-is-the-algorithm-to-compute-the-amazon-s3-etag-for-a-file-larger-than-5gb/19896823#19896823

参考

https://docs.aws.amazon.com/AmazonS3/latest/API/RESTCommonResponseHeaders.html