タスク 1: 署名バージョン 4 の正規リクエストを作成する
署名プロセスを開始するには、リクエストからの情報を含む文字列を標準化された (正規) 形式で作成します。これにより、リクエストを受け取ると、AWS はお客様が計算したのと同じ署名を計算できるようになります。
正規バージョンのリクエストを作成するには以下の手順に従ってください。そうしなければ、使用しているバージョンと AWS によって計算されたバージョンが一致せず、リクエストが拒否されます。
以下の例は、正規リクエストを作成する擬似コードを示しています。
例 正規リクエストの擬似コード
CanonicalRequest =
HTTPRequestMethod
+ '\n' +CanonicalURI
+ '\n' +CanonicalQueryString
+ '\n' +CanonicalHeaders
+ '\n' +SignedHeaders
+ '\n' + HexEncode(Hash(RequestPayload
))
この擬似コードでは、Hash
は、メッセージダイジェストを生成する関数(通常は SHA-256)を表します。(このプロセスの後半で、使用しているハッシュアルゴリズムを指定します)。HexEncode
は、ダイジェストの Base 16 エンコードを小文字で返す関数です。たとえば、HexEncode("m")
は、6d
ではなく 6D
という値を返します。各入力バイトは、正確に 2 個の 16 進数文字として表す必要があります。
署名バージョン 4 では、正規のリクエストをエンコードするために特定の文字エンコードを使用する必要はありません。ただし、一部の AWS サービスでは、特定のエンコードが必要な場合があります。詳細については、そのサービスのドキュメントを参照してください。
次の例は、IAM に対する正規形式のリクエストを作成する方法を示しています。元のリクエストは、クライアントから AWS に送信されるときにこのようになる場合がありますが、この例には署名情報がまだ含まれていません。
例 リクエスト
GET https://iam.amazonaws.com/?Action=ListUsers&Version=2010-05-08 HTTP/1.1 Host: iam.amazonaws.com Content-Type: application/x-www-form-urlencoded; charset=utf-8 X-Amz-Date: 20150830T123600Z
前の例は、ListUsers
(ホスト) に対する AWS Identity and Access Management API (アクション) 呼び出しを作成する GET リクエスト (メソッド) です。このアクションは Version
パラメータを取ります。
正規リクエストを作成するには、各ステップの次のコンポーネントを単一の文字列に連結します。
-
最初に HTTP リクエストメソッド (
GET
、PUT
、POST
など) を指定し、その後に改行文字を置きます。例 リクエスト方法
GET
-
正規 URI パラメータを追加し、その後に改行文字を置きます。正規 URI は、URI の絶対パス要素の URI エンコードバージョンで、HTTP ホストヘッダーからクエリ文字列パラメータ (存在する場合) を開始する疑問符 ("?") までのすべてを含みます。
RFC 3986
に従って URI のパスを正規化します。冗長および相対パス要素を削除します。各パスセグメントでは、2 回の URI エンコードが必要です (Amazon S3 は例外で、1 回のみ URI エンコードを取得します)。 例 エンコードを使用した正規 URI
/documents%2520and%2520settings/
注記 この例外として、Amazon S3 へのリクエストのための URI パスを標準化しません。たとえば、
my-object//example//photo.user
というオブジェクトを持つバケットがある場合は、そのパスを使用します。パスをmy-object/example/photo.user
に標準化すると、リクエストが失敗します。詳細については、Amazon Simple Storage Service API リファレンスのタスク 1: 正規リクエストを作成するを参照してください。絶対パスが空値の場合は、フォワードスラッシュ (/) を使用します。この IAM リクエスト例では、URI のホストに続くものが何もないため、絶対パスは空です。
例 正規 URI
/
-
正規クエリ文字列を追加し、その後に改行文字を置きます。リクエストにクエリ文字列が含まれていない場合は、空の文字列 (主に空白行) を使用します。このリクエスト例には次のクエリ文字列が含まれます。
例 正規クエリ文字列
Action=ListUsers&Version=2010-05-08
正規クエリ文字列を作成するには、次の手順を実行します。
-
パラメーター名を文字コードポイントで昇順にソートします。名前が重複しているパラメータは、値でソートする必要があります。たとえば、大文字 F で始まるパラメーター名は、小文字 b で始まるパラメーター名より前に置きます。
-
以下の規則に従って各パラメータ名と値を URI エンコードします。
-
RFC 3986
が定義する非予約文字である A ~ Z、a ~ z、0 ~ 9、ハイフン (-)、アンダースコア ( _ )、ピリオド (.)、およびチルド (~) を、URI がエンコードすることはありません。 -
他のすべての文字についても、%XY によるパーセントエンコードが必要です。X および Y には 16 進数文字(0~9 および大文字の A ~ F)が入ります。たとえば、スペース文字は %20 として(一部のエンコードスキームのように '+' を使用せずに)エンコードする必要があり、拡張 UTF-8 文字は
%XY%ZA%BC
形式でエンコードする必要があります。 -
パラメータ値の等号 (=) 文字を二重エンコードします。
-
-
ソートされたリストの最初のパラメータ名から開始して、正規クエリ文字列を構築します。
-
各パラメータに、URI エンコードされるパラメーター名、等号文字 (=)、URI エンコードされるパラメーター値を順に追加します。値のないパラメータには空の文字列を使用します。
-
リストの最後の値を除き、各パラメーター値の後ろにアンパサンド文字 (&) を追加します。
クエリ API の使用方法の 1 つとして、すべてのリクエストパラメーターをクエリ文字列に配置することができます。たとえば、Amazon S3 の場合、この方法で署名付き URL を作成できます。その場合、正規クエリ文字列には、リクエストのパラメータだけでなく、ハッシュアルゴリズム、認証情報スコープ、日付、および署名付きヘッダーパラメータなどの署名プロセスの一部で使用されるパラメータも含める必要があります。
次の例は、認証情報を含むクエリ文字列を示します。この例は読みやすいように改行してありますが、実際のコードでは、正規クエリ文字列はひと続きのテキストにする必要があります。
例 クエリ文字列の認証パラメータ
Action=ListUsers& Version=2010-05-08& X-Amz-Algorithm=AWS4-HMAC-SHA256& X-Amz-Credential=AKIDEXAMPLE%2F20150830%2Fus-east-1%2Fiam%2Faws4_request& X-Amz-Date=20150830T123600Z& X-Amz-SignedHeaders=content-type%3Bhost%3Bx-amz-date
認証パラメーターの詳細については、「タスク 2: 署名バージョン 4 の署名文字列を作成する」を参照してください。
注記 AWS Security Token Service (AWS STS) から提供された一時的なセキュリティ認証情報を使用してリクエストに署名できます。このプロセスは長期的な認証情報を使用する場合と同じですが、クエリ文字列に署名情報を追加する際に、セキュリティトークン用の追加のパラメーターを追加する必要があります。パラメーター名は
X-Amz-Security-Token
です。パラメーター値は URI エンコードされたセッショントークン (一時的なセキュリティ認証情報を取得する際に AWS STS から受け取った文字列) です。一部のサービスでは、正式な (署名付き) クエリ文字列に
X-Amz-Security-Token
クエリパラメーターを含める必要があります。その他のサービスでは、署名の計算後に、X-Amz-Security-Token
パラメーターを末尾に追加します。詳細については、そのサービスの API リファレンスドキュメントを参照してください。 -
-
正規ヘッダーを追加し、その後に改行文字を置きます。正規ヘッダーは、 署名付きリクエストに含めるすべての HTTP ヘッダーのリストで構成されます。
HTTP/1.1 リクエストの場合は、少なくとも
host
ヘッダーを含める必要があります。content-type
のような標準ヘッダーはオプションです。HTTP/2 リクエストの場合は、:authority
ヘッダーの代わりにhost
ヘッダーを含める必要があります。別のサービスでは、他のヘッダーが必要な場合があります。例 正規ヘッダー
content-type:application/x-www-form-urlencoded; charset=utf-8\n host:iam.amazonaws.com\n x-amz-date:20150830T123600Z\n
正規ヘッダーリストを作成するには、すべてのヘッダー名を小文字に変換し、先頭および末尾のスペースを削除します。ヘッダー値にある連続スペースを単一のスペースに変換します。
次の擬似コードは、ヘッダーの正規リストを作成する方法を記述しています。
CanonicalHeaders =
CanonicalHeadersEntry0
+CanonicalHeadersEntry1
+ ... +CanonicalHeadersEntryN
CanonicalHeadersEntry = Lowercase(HeaderName
) + ':' + Trimall(HeaderValue
) + '\n'Lowercase
は、すべての文字を小文字に変換する関数を表します。Trimall
関数は値の前後のスペースを削除し、連続スペースを単一のスペースに変換します。正規ヘッダーリストを構築するには、(小文字の) ヘッダーを文字コードでソートし、ヘッダー名を繰り返し処理します。次のルールに従って各ヘッダーを作成します。
-
小文字のヘッダー名とそれに続くコロンを追加します。
-
このヘッダーの値のカンマ区切りリストを追加します。複数の値を持つヘッダーの値はソートしません。
-
改行 (
\n
) を追加します。
次の例では、より複雑なヘッダーのセットをその正規形式と比較します。
例 元のヘッダー
Host:iam.amazonaws.com\n Content-Type:application/x-www-form-urlencoded; charset=utf-8\n My-header1: a b c \n X-Amz-Date:20150830T123600Z\n My-Header2: "a b c" \n
例 正規形式
content-type:application/x-www-form-urlencoded; charset=utf-8\n host:iam.amazonaws.com\n my-header1:a b c\n my-header2:"a b c"\n x-amz-date:20150830T123600Z\n
注記 各ヘッダーの最後には、リスト全体の終わりを示す改行文字を置きます。
正規形式では、以下の変更が行われました。
-
ヘッダー名は小文字に変換されました。
-
ヘッダーは文字コードによってソートされました。
-
先頭と末尾のスペースは
my-header1
およびmy-header2
の値から削除されています。 -
a b c
値とmy-header1
値では、my-header2
にある連続スペースが単一のスペースに変換されています。
注記 AWS Security Token Service (AWS STS) から提供された一時的なセキュリティ認証情報を使用してリクエストに署名できます。このプロセスは長期的な認証情報を使用する場合と同じですが、
Authorization
ヘッダーに署名情報を追加する際に、セキュリティトークン用の追加の HTTP ヘッダーを追加する必要があります。ヘッダー名はX-Amz-Security-Token
です。ヘッダー値はセッショントークン (一時的なセキュリティ認証情報を取得する際に AWS STS から受け取った文字列) です。 -
-
署名付きヘッダーを追加し、その後に改行文字を置きます。この値は、正規ヘッダーに含めたヘッダーのリストです。このヘッダーのリストを追加することで、リクエストのどのヘッダーが署名プロセスの一部であり、リクエストを承認するために AWS がどのヘッダー (プロキシによって追加される追加のヘッダーなど) を無視できるかを AWS に伝えます
HTTP/1.1 リクエストの場合、
host
ヘッダーは署名付きヘッダーとして含める必要があります。:authority
ヘッダーではなく、host
ヘッダーを含める HTTP/2 リクエストの場合は、署名付きヘッダーとして:authority
ヘッダーを含める必要があります。日付またはx-amz-date
ヘッダーを含める場合、そのヘッダーを署名付きヘッダーのリストにも含める必要があります。署名付きヘッダーのリストを作成するために、すべてのヘッダー名を小文字に変換して文字コードによりソートし、セミコロンを使用してヘッダー名を区切ります。次の擬似コードは、署名付きヘッダーのリストを作成する方法を示しています。
Lowercase
は、すべての文字を小文字に変換する関数です。SignedHeaders = Lowercase(
HeaderName0
) + ';' + Lowercase(HeaderName1
) + ";" + ... + Lowercase(HeaderNameN
)小文字コードによってソートされた一連のヘッダー名を繰り返すことで署名付きヘッダーリストを構築します。最後を除く各ヘッダー名について、ヘッダー名にセミコロン (';') を追加して次のヘッダー名と区切ります。
例 署名付きヘッダー
content-type;host;x-amz-date\n
-
SHA256 のようなハッシュ (ダイジェスト) 関数を使用して、HTTP または HTTPS リクエストの本文のペイロードからハッシュ値を作成します。署名バージョン 4 では、ペイロードにテキストをエンコードするための特定の文字エンコードを使用する必要はありません。ただし、一部の AWS サービスでは、特定のエンコードが必要な場合があります。詳細については、そのサービスのドキュメントを参照してください。
例 ペイロードの構造
HashedPayload = Lowercase(HexEncode(Hash(
requestPayload
)))署名文字列を作成するときには、ペイロードをハッシュするのに使用した署名アルゴリズムを指定します。たとえば、SHA256 を使用した場合、署名アルゴリズムとして AWS4-HMAC-SHA256 を指定します。ハッシュペイロードは、小文字の 16 進文字列として表す必要があります。
ペイロードが空の場合、ハッシュ関数への入力として空の文字列を使用します。IAM の例では、ペイロードは空です。
例 ハッシュされたペイロード (空の文字列)
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
-
最終的な正規リクエストを作成するには、各手順のすべてのコンポーネントを単一の文字列として結合します。前述のとおり、各コンポーネントは改行文字で終わります。前記の正規リクエストの擬似コードに従う場合、結果の正規リクエストは次の例のとおりです。
例 正規リクエスト
GET / Action=ListUsers&Version=2010-05-08 content-type:application/x-www-form-urlencoded; charset=utf-8 host:iam.amazonaws.com x-amz-date:20150830T123600Z content-type;host;x-amz-date e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
-
ペイロードをハッシュする際に使用したのと同じアルゴリズムを使用して、正規リクエストのダイジェスト (ハッシュ) を作成します。
注記 署名バージョン 4 では、ダイジェストを計算する前に、正規のリクエストをエンコードするために特定の文字エンコードを使用する必要はありません。ただし、一部の AWS サービスでは、特定のエンコードが必要な場合があります。詳細については、そのサービスのドキュメントを参照してください。
ハッシュされた正規リクエストは、小文字の 16 進数文字の文字列として表す必要があります。次の例は、SHA-256 を使用して正規リクエスト例をハッシュした結果を示しています。
例 ハッシュされた正規リクエスト
f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59
署名文字列の一部としてハッシュされた正規リクエストを タスク 2: 署名バージョン 4 の署名文字列を作成する に含めます。