aws s3v4 署名バージョン
aws s3 は version4 より署名プロセスが変わっています
https://docs.aws.amazon.com/ja_jp/general/latest/gr/signature-version-4.html
署名作成の流れ
- 署名に必要なキーを作成する(本記事はここ)
- 1.で作成したキーを使って署名を作成する
各言語での署名キー作成方法
各言語の署名キー作成フローは以下の文書にまとまっています。しかしながら、Java
, .NET (C#)
, Python
, Ruby
, Javascript
のサンプルコードはあっても、Golangのサンプルコードは存在しません
https://docs.aws.amazon.com/ja_jp/general/latest/gr/signature-v4-examples.html
そのため、本記事ではGolangで version4 用の署名取得処理のサンプルコードを載せることとします
ちなみにですが、本記事では署名キーを作成する部分の説明であり、署名作成のために前もって準備しておかなければならない処理が存在します。それについては、後日記事を執筆しようと思います。
公式のサンプルを乗せて比較できるようにしていますが、さっさとGolangでの実装方法を知りたい人は、こちらから
署名に必要なキーを作成する(Java-公式サンプルコード)
公式のサンプルコードにならって説明します
言語は何でも良いのですが、Java を載せておきます
HmacSHA256
はある文字列を、あるキー(byte配列)を使ってhash化する関数です
getSignatureKey
は特定の文字列をhash化して署名を得る処理です
ある文字列をハッシュ化した[]byteをキーとして、ハッシュを重ねていくことで、最終生成物の署名を得ることができます。
version4では、
- date
- region
- service
- s3のsecretキー
を使って署名を作成します
static byte[] HmacSHA256(String data, byte[] key) throws Exception {
String algorithm="HmacSHA256";
Mac mac = Mac.getInstance(algorithm);
mac.init(new SecretKeySpec(key, algorithm));
return mac.doFinal(data.getBytes("UTF-8"));
}
static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception {
byte[] kSecret = ("AWS4" + key).getBytes("UTF-8");
byte[] kDate = HmacSHA256(dateStamp, kSecret);
byte[] kRegion = HmacSHA256(regionName, kDate);
byte[] kService = HmacSHA256(serviceName, kRegion);
byte[] kSigning = HmacSHA256("aws4_request", kService);
return kSigning;
}
署名に必要なキーを作成する(Golang)
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
s3Secretkey := "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY"
dateStamp := "20120215"
regionName := "us-east-1"
serviceName := "iam"
signatureKey := getSignature(s3Secretkey, dateStamp, regionName, serviceName)
fmt.Println(signatureKey) // f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d
}
func getBinaryByMakeHMAC(msg string, key []byte) ([]byte, error) {
mac := hmac.New(sha256.New, key)
_, err := mac.Write([]byte(msg))
return mac.Sum(nil), err
}
func getSignature(s3SecretKey, dateStamp, regionName, serviceName string) string {
kSecret := []byte("AWS4" + s3SecretKey)
kDate, _ := getBinaryByMakeHMAC(dateStamp, kSecret)
kRegion, _ := getBinaryByMakeHMAC(regionName, kDate)
kService, _ := getBinaryByMakeHMAC(serviceName, kRegion)
kSigning, _ := getBinaryByMakeHMAC("aws4_request", kService)
return hex.EncodeToString(kSigning)
}
サンプルコード
https://play.golang.org/p/91EMyZsbvsx
公式が用意している以下のサンプルデータの場合に、出力される値を確認しながら進めるとデバッグしやすいです
key = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
dateStamp = '20120215'
regionName = 'us-east-1'
serviceName = 'iam'
署名キーを得るまでの中間値
kSecret = '41575334774a616c725855746e46454d492f4b374d44454e472b62507852666943594558414d504c454b4559'
kDate = '969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d'
kRegion = '69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c'
kService = 'f72cfd46f26bc4643f06a11eabb6c0ba18780c19a8da0c31ace671265e3c87fa'
kSigning = 'f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d'
サンプルコードでこの中間値を得るためには、ハッシュ化した後の[]byteを hex.EncodeToString([]byte)
にて[]byteをhex(16進数)へと変換する必要があることに注意してください