S3のRESTリクエストを署名バージョン4で行う

**リクエストの認証 (AWS 署名バージョン 2)**
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/auth-request-sig-v2.html
>2019 年 6 月 24 日以降、Amazon S3 は署名バージョン 4 を使用して署名された API リクエストのみを受けつけます。

そもそもSDKを使用しているのであればバージョンアップすれば良いだけかと思いますが、この世のどこかにはもしかしたらRESTリクエストを使用した独自のクラスを実装をしているシステムがあるかもしれませんね。
SDKを使用した仕様へ変更するにも時間が、、、な場合は、RESTリクエストを署名バージョン4へ変更する必要が出てきそうです。
※公式見るだけでなんとかなれば良かったのですが、結局、先人の知恵をお借りしてます。
**参考** Amazon S3 REST API with curl(https://czak.pl/2015/09/15/s3-rest-api-with-curl.html)

##公式の手順通りに進める
**署名バージョン 4 を使用して AWS リクエストに署名する**
https://docs.aws.amazon.com/ja_jp/general/latest/gr/sigv4_signing.html

目的はファイルの取得という事で下記の条件で進めます。

|対象のバケット|対象のファイル|実行日時(タイムスタンプ)|
|:------------|-------------|----------------------|
|hogebucket|hogefolder/hogefile.txt|20190407T150000Z|

|ACCESS KEY|SECRET KEY|
|:------|----------|
|AKIAIEXAMPLE|secretkey/hogehoge/example|
※タイムスタンプは実行日時から15分後までの物を使用します。それ以降の物はサーバーで弾かれます。

##タスク 1: 署名バージョン 4 の正規リクエストを作成する
今回の条件では下記のリクエストとなります。

```
GET /hogefolder/hogefile.txt HTTP/1.1
Host: hogebucket.s3.amazonaws.com
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date: 20190407T150000Z
```
※x-amz-content-sha256には、空文字をsha256でハッシュ化した物です。空文字であれば常に固定です。

ルールに従い正規ヘッダーを作成

```
host:hogebucket.s3.amazonaws.com
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20190407T043000Z
```

署名付きヘッダーの作成

```
host;x-amz-content-sha256;x-amz-date
```

今回はS3からファイルを取得するだけなのでペイロードはありません。
その為、ハッシュペイロードには、x-amz-content-sha256に使用した物と同じ物(空文字をsha256でハッシュ化した物)を使用します。

```
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
```

改行コードも含めて、正規リクエストの完成

```
GET\n
/hogefolder/hogefile.txt\n
\n
host:hogebucket.s3.amazonaws.com\n
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n
x-amz-date:20190407T150000Z\n
\n
host;x-amz-content-sha256;x-amz-date\n
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
```

正規リクエストをSHA-256でハッシュ化

```
echo -en "GET\\n/hogefolder/hogefile.txt\\n\\nhost:hogebucket.s3.amazonaws.com\\nx-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\\nx-amz-date:20190407T150000Z\\n\\nhost;x-amz-content-sha256;x-amz-date\\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" | openssl dgst -sha256
```

ハッシュ文字列を取得できました。


```
622bb475b833925daf1bed7ce7c708055f6feded404de7c360aa4bcbda750776
```


##タスク 2: 署名バージョン 4 の署名文字列を作成する
タスク1で使用したリクエスト

```
GET /hogefolder/hogefile.txt HTTP/1.1
Host: hogebucket.s3.amazonaws.com
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date: 20190407T150000Z
```

必要な情報を埋めて、タスク1で作成したハッシュを最下部に配置し、署名対象の文字列を作成します。

```
AWS4-HMAC-SHA256\n
20190407T150000Z\n
20190407/ap-northeast-1/s3/aws4_request\n
622bb475b833925daf1bed7ce7c708055f6feded404de7c360aa4bcbda750776
```

※ap-northeast-1リージョンを指定してますが、ここはアクセス元に応じて変えなくてはならないようです。
間違えても下記のようにエラーメッセージに「○○にしてくれ」と記載されるので状況に応じて変更してください。
`<Message>The authorization header is malformed; the region 'us-east-1' is wrong; expecting 'ap-northeast-1'</Message>`


##タスク 3: AWS 署名バージョン 4 の署名を計算する

署名キーを取得
ここは面倒なので先人の知恵のスクリプトファイルをお借りします。

```signing_key.sh
#!/bin/bash
function hmac_sha256 {
  key="$1"
  data="$2"
  echo -n "$data" | openssl dgst -sha256 -mac HMAC -macopt "$key" | sed 's/^.* //'
}

secret="$1"
date="$2"
region="$3"
service="$4"

# Four-step signing key calculation
dateKey=$(hmac_sha256 key:"AWS4$secret" $date)
dateRegionKey=$(hmac_sha256 hexkey:$dateKey $region)
dateRegionServiceKey=$(hmac_sha256 hexkey:$dateRegionKey $service)
signingKey=$(hmac_sha256 hexkey:$dateRegionServiceKey "aws4_request")

echo $signingKey
```

コマンドで一発

```
./signing_key.sh secretkey/hogehoge/example 20190407 ap-northeast-1 s3
```

署名キーが取得できました。

```
0dae14d5e8d22788b2efc0665bcdac7bf46a263c2c45176c0ef237ecc494738c
```

タクス2で作成した「署名対象の文字列」に「署名キー」を使用して署名を計算

```
echo -en "AWS4-HMAC-SHA256\\n20190407T150000Z\\n20190407/ap-northeast-1/s3/aws4_request\\n622bb475b833925daf1bed7ce7c708055f6feded404de7c360aa4bcbda750776"| openssl dgst -sha256 -mac HMAC  -macopt hexkey:0dae14d5e8d22788b2efc0665bcdac7bf46a263c2c45176c0ef237ecc494738c
```

署名を取得

```
36fd8c3446b36f6c99532dbe1262d34f8d0166c8e7b1f8ca330ee90f7ae765d9
```

##タスク 4: HTTP リクエストに署名を追加する

あとはCURLで叩くだけ

```
curl -v https://hogebucket.s3.amazonaws.com/hogefolder/hogefile.txt \
-H "Authorization: AWS4-HMAC-SHA256 Credential=AKIAIEXAMPLE/20190407/ap-northeast-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=36fd8c3446b36f6c99532dbe1262d34f8d0166c8e7b1f8ca330ee90f7ae765d9" \
-H "x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \
-H "x-amz-date: 20190407T090552Z"
```