|« PreviousNext »|
|Did this page help you? Yes | No | Tell us about it...|
To begin the signing process, you create a string that includes information from your request in a standardized (canonical) format. Formatting the request into an unambiguous, canonical format before signing it ensures that when AWS receives the request, it calculates the same signature that you calculated. (Non-standardized formatting can result in you and AWS calculating different signatures for the request, and the request will be denied.)
The following example shows the pseudocode for how to create a canonical request.
Canonical request pseudocode
HTTPRequestMethod+ '\n' +
CanonicalURI+ '\n' +
CanonicalQueryString+ '\n' +
CanonicalHeaders+ '\n' +
SignedHeaders+ '\n' + HexEncode(Hash(
In this pseudocode,
Hash represents a function that produces a message digest,
such as SHA-256. (Later in the process you specify which hashing algorithm you're
HexEncode represents a function that returns the base-16
encoding of the digest in lowercase characters. For example,
HexEncode("m") returns the value
6d rather than
6D. Each input byte must be represented as exactly two hexadecimal
To show you how to construct the canonical form of an HTTP or HTTPS request, let's use the following sample request. This is what a request might look like as it is sent from the browser to AWS, except that this example does not include the signing information yet.
POST http://iam.amazonaws.com/ HTTP/1.1 host: iam.amazonaws.com Content-type: application/x-www-form-urlencoded; charset=utf-8 x-amz-date: 20110909T233600Z Action=ListUsers&Version=2010-05-08
The sample request is a POST request (method) that makes a
(action) call to AWS Identity and Access Management (host). This action takes only the optional
To create a canonical request, concatenate the following components from each step into a single string:
Start with the HTTP request method (GET, PUT, POST, etc.).
CanonicalURI parameter. This is the URI-encoded version of the
absolute path component of the URI—everything from the HTTP host
header to the question mark character ('?') that begins the query string
parameters. Then add a newline character.
Normalize URI paths according to RFC 3986 by removing redundant and relative path components. Each path segment must be URI-encoded. If the absolute path is empty, use a forward slash (/).
CanonicalQueryString parameter. If the request does not include a
query string, set the value of
CanonicalQueryString to an empty
To construct the canonical query string, complete the following steps:
URI encode each parameter name and value according to the following rules:
Do not URL-encode any of the unreserved characters that RFC 3986 defines: A-Z, a-z, 0-9, hyphen ( - ), underscore ( _ ), period ( . ), and tilde ( ~ ).
Percent-encode all other characters with %XY, where X and Y are hexadecimal characters (0-9 and uppercase A-F).
For example, the space character must be encoded as %20 (and not '+', as some encoding schemes do) and extended UTF-8 characters must be in the form %XY%ZA%BC.
Sort the encoded parameter names by character code (that is, in strict ASCII order). For example, a parameter name that begins with the uppercase letter F (ASCII code 70) precedes a parameter name that begins with a lowercase letter b (ASCII code 98).
Build the canonical query string by starting with the first parameter name in the sorted list.
For each parameter, append the URI-encoded parameter name, followed by the character '=' (ASCII code 61), followed by the URI-encoded parameter value.
Use an empty string for parameters that have no value.
Append the character '&' (ASCII code 38) after each parameter value except for the last value in the list.
In some cases, you might construct a request where all the authorization parameters are in the query string, such as pre-signed URLs for Amazon S3. In such cases, the canonical query string must include the algorithm, credential scope, date, and signed headers parameters, as shown in the following example:
Authorization parameters in a query string
Action=ListUsers& Version=2010-05-08& X-Amz-Algorithm=AWS4-HMAC-SHA256& X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20110909%2Fus-east-1%2Fiam%2Faws4_request& X-Amz-Date=20110909T233600Z& X-Amz-SignedHeaders=content-type%3Bhost%3Bx-amz-date
The previous example was formatted with line breaks for readability; the canonical query string must be one continuous line of text. For more information about the authorization parameters, see Task 2: Create a String to Sign for Signature Version 4.
CanonicalHeaders parameter, which is a list of all the HTTP headers
that you are including in the request. You must include a
header and any other headers that might be required by the service you're
Sample request: CanonicalHeaders
content-type:application/x-www-form-urlencoded; charset=utf-8\n host:iam.amazonaws.com\n x-amz-date:20110909T233600Z\n
To create a canonical headers list, convert all header names to lowercase and trim excess white space characters out of the header values. When you trim, remove leading spaces and trailing spaces, and convert sequential spaces in the value to a single space. However, do not remove extra spaces from any values that are inside quotation marks.
The following pseudocode describes how to construct the canonical list of headers:
CanonicalHeadersEntry1+ ... +
CanonicalHeadersEntryNCanonicalHeadersEntry = Lowercase(
HeaderName) + ':' + Trimall(
HeaderValue) + '\n'
Lowercase represents a function that converts all characters to lowercase.
Trimall function removes excess white space before and
after values and from inside non-quoted strings, per RFC 2616 Section
Build the canonical headers list by iterating through the collection of header names, sorted by lowercase character code. Construct each header by using the following rules:
Append the lowercase header name followed by a colon.
Append a comma-separated list of values for that header. If there are duplicate headers, the values are comma-separated. Do not sort the values in headers that have multiple values.
Append a newline ('\n').
To show an additional example, the following two samples compare a more complex set of headers with their canonical form:
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:20120228T030031Z\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:20120228T024136Z\n
In the canonical form, the following changes were done:
The header names have been converted to lowercase characters.
The headers have been sorted by character code.
Removed extra spaces for the value of
my-header1 because it's not in
No extra spaces were removed for the value of
my-header2 because it's in
Removed leading spaces for the
SignedHeaders parameter, which is the list of HTTP headers that you
included in the canonical headers. By adding this list of headers, you tell
AWS which headers in the received request are part of the signing process;
AWS knows that any additional headers (for example, any headers added by a
proxy) can be ignored for purposes of validating the request.
host header must be included as a signed header. If you include a date
x-amz-date header, you must also include that header in the
list of signed headers.
To create the signed headers list, convert all header names to lowercase,
sort them by character code, and use a semicolon to separate the header
names. The following pseudocode describes how to construct a list of signed
LOWERCASE represents a function that converts all
characters to lowercase.
SignedHeaders = Lowercase(HeaderName0) + ';' + Lowercase(HeaderName1) + ... + Lowercase(HeaderNameN)
Build the signed headers list by iterating through the collection of header names, sorted by lowercase character code. For each header name except the last, append a semicolon (';') to the header name to separate it from the following header name.
Add a hashed (digest) version of the payload from the body of the HTTP or HTTPS request:
If the payload is empty, use the empty string as the input to the hash function. For example, suppose that your request includes the following payload:
The following example shows the result of using SHA-256 to hash the example payload.
(When you create the string to sign (Task 2: Create a String to Sign for
Signature Version 4), you will specify the signing
algorithm that you used to hash the payload. For example, if you used SHA256, you will
AWS4-HMAC-SHA256 as the signing algorithm.) The hashed payload must
be represented as a lowercase hexadecimal string.
To construct the final canonical request, combine all the components from each step as a single string. If you follow the canonical request pseudocode, the resulting canonical request is shown in the following example:
Sample request: Canonical form
POST / content-type:application/x-www-form-urlencoded; charset=utf-8 host:iam.amazonaws.com x-amz-date:20110909T233600Z content-type;host;x-amz-date b6359072c78d70ebee1e81adcbab4f01bf2c23245fa365ef83fe8f1f955085e2
Create a digest (hash) of the canonical request by using the same algorithm that you used to hash the payload. The hashed canonical request must be represented as a string of lowercase hexademical characters. The following sample example shows the result of using SHA-256 to hash the example canonical request.
Sample request: Hashed canonical request
You include the hashed canonical request as part of the string to sign in Task 2: Create a String to Sign for Signature Version 4.