EtagをつかってS3にアップロードしたファイルの整合性をたしかめてみる（マルチパートアップロードあり）

※2024年7月追記
S3のEタグ周りについては本記事を含んで下記の記事をシリーズとして投稿しています。

- [EtagをつかってS3にアップロードしたファイルの整合性をたしかめてみる（マルチパートアップロードなし）](https://qiita.com/SAITO_Keita/items/29cf207b969537b2b68b)
- [EtagをつかってS3にアップロードしたファイルの整合性をたしかめてみる（マルチパートアップロードあり）](https://qiita.com/SAITO_Keita/items/21f9b5390c3487ac9957)
- [AWSマネジメントコンソールからS3にマルチパートアップロードした時の分割サイズについて](https://qiita.com/SAITO_Keita/items/99691f77b00b07a193bf)
- [PowerShellでS3のEtagを計算してみる（暗号化なし＆SSE-S3&マルチパートアップロード対応）](https://qiita.com/SAITO_Keita/items/5cf16cc82c4e8fd0ee56)

追記おしまい

[EtagをつかってS3にアップロードしたファイルの整合性をたしかめてみる（マルチパートアップロードなし）](https://qiita.com/SAITO_Keita/items/29cf207b969537b2b68b)

前編として上記記事を投稿しました。

本記事ではS3にアップロードしたファイルのEtagが、暗号化方式とマルチパートアップロードでどうなるか確認していきます。

## ドキュメント

[aws-cli / s3 cp](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/cp.html)

[Content-MD5 と ETag を使用して、アップロードされたオブジェクトを検証する](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/checking-object-integrity.html#checking-object-integrity-etag-and-md5)

## 検証に利用する環境

- Windows 10 21H2
- PowerShell 7.4.0-preview.4
- aws-cli/2.13.3 Python/3.11.4 Windows/10 exe/AMD64 prompt/off

## aws-cliでマルチパートアップロードありでアップロードして確認してみる

前回の記事ではマルチパートアップロードを無効にしてアップロードするため`aws s3 api put-object`を利用しました。

今回はマルチパートアップロードしたいので、`aws s3 cp`コマンドを利用します。
今回、`aws-cli`デフォルトの閾値8mbを利用しているため、10mbのtestfileを`aws s3 cp`でアップロードするとマルチパートアップロードが有効となります。

```powershell:PowerShellでファイルを作成してアップロード
# 前回の記事で下記コマンドで作成したtestfileを利用する
# fsutil file createnew .\testfile $(10mb)
# ファイルハッシュはF1C9645DBC14EFDDC7D8A322685F26EB
# SSE-S3でキーtestfile-sse-s3としてtestfileをアップロード

aws s3 cp ./testfile s3://<<バケット名>>/testfile-sse-s3-multipart --sse AES256

# SSE-KMSでキーtestfile-sse-kmdとしてtestfileをアップロード
aws s3 cp ./testfile s3://<<バケット名>>/testfile-sse-kms-multipart --sse aws:kms --sse-kms-key-id <<KMSキーID>>

# SSE-Cでキーtestfile-sse-cとしてtestfileをアップロード

# AESで利用する鍵を設定（32バイトの任意の文字列）
$key="7tkJjz;uqVMd@?yIg2<1i9lLsGFc=5AR"
aws s3 cp ./testfile s3://<<バケット名>>/testfile-sse-c-multipart --sse-c AES256 --sse-c-key $key
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/c89e5c2c-3a30-7564-d1b4-28326525e43f.png)


上記のように`aws-cli`でtestfileをそれぞれの暗号化方式でアップロードしました。

## アップロードしたファイルのEtagを確認してみる

各オブジェクトのEtagを`s3api head-object`で確認してみます。

```PowerShell
aws s3api head-object --bucket <<バケット名>> --key testfile-sse-s3-multipart --query "ETag"
aws s3api head-object --bucket <<バケット名>> --key testfile-sse-kms-multipart --query "ETag"

# アップロード時に利用した鍵を利用
$key="7tkJjz;uqVMd@?yIg2<1i9lLsGFc=5AR"
aws s3api head-object --bucket <<バケット名>> --key testfile-sse-c-multipart --query "ETag" --sse-customer-algorithm AES256 --sse-customer-key $key
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/5858cb77-76ae-d962-e07a-b8bce321c8aa.png)


|暗号化|ファイル名|Etag|
|---|---|---|
|sse-s3|testfile-sse-s3-multipart|669fdad9e309b552f1e9cf7b489c1f73-2|
|sse-kms|testfile-sse-kms-multipart|2f7edf972e5e9ca78c2a49609b6e3e18-2|
|sse-c|testfile-sse-c-multipart|3a5f6568c71a06c1dff16027afc6702e-2|

今回、マルチパートアップロードしたため、ローカルファイルのMD5`F1C9645DBC14EFDDC7D8A322685F26EB`と一致するファイルはありませんでした。

マルチパートアップロードした場合は、EtagがMD5にならない事が確認できました。
が、このままでは整合性の確認はできません。

## マルチパートアップロードの場合どうするか

[マルチパートアップロードにパートレベルのチェックサムを使用する](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/checking-object-integrity.html#large-object-checksums)

ドキュメントを確認してみるとマルチパートアップロードの場合は、分割されたファイルごとにMD5を計算し、これらを連結し、連結した値のMD5をEtagとして入力するようです。

この処理を再現してくれる機能は`aws-cli`にはないようです。

ファイルを分割してそれぞれにMD5を計算して、連結して、連結した値のMD5を計算する処理を書く必要がありますが。

探してみた所、下記のようなbashで実装されたライブラリがありました。

[antespi/s3md5
](https://github.com/antespi/s3md5)

こちらを利用して計算してみたところ下記のようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/cdaeeaa4-b701-efbe-eb1b-b3a825310d77.png)

`669fdad9e309b552f1e9cf7b489c1f73-2`

こちらの値は、`sse-s3`でアップロードしたEtagと一致しました。

## 総評

マルチアップロードの有無関係なく、Etagで整合性が確認できるのはsse-s3となるようです。

他の暗号化方式を利用している場合でファイルの整合性を確認したい場合は、追加のチェックサムを利用しましょう。