Menu
Alexa Top Sites
Developer Guide

Alexa Top Sites - Calculating Signatures

[Note] Note

The best way to learn how to sign requests is to read the AWS Signature V4 documentation and the code samples in the Resource Center for examples using Java, C#, PHP, Perl and Ruby.">

[Important] Important

Signature version 4 is described below. Signature V2 will be deprecated on Feb 1, 2018. As of November 25, 2017 you must use signature version 4.

To create the signature

  1. Create the canonicalized request string that you need later in this procedure:

    Pseudocode of a canonical request

    CanonicalRequest =
      HTTPRequestMethod + '\n' +
      CanonicalURI + '\n' +
      CanonicalQueryString + '\n' +
      CanonicalHeaders + '\n' +
      SignedHeaders + '\n' +
      HexEncode(Hash(RequestPayload))
      
    1. Start with the HTTP request method followed by a newline character.

      GET
    2. Add the canonical URI parameter, followed by a newline character. The canonical URI is the URI-encoded version of the absolute path component of the URI, which is everything in the URI from the HTTP host to the question mark character ("?") that begins the query string parameters (if any).

      Normalize URI paths according to RFC 3986. Remove redundant and relative path components. Each path segment must be URI-encoded.

      Example canonical URI

      /api
    3. Add the canonical query string, followed by a newline character.

      Example canonical query string

      Action=TopSites&CountryCode=US&ResponseGroup=Country

      To construct the canonical query string, complete the following steps:

      1. Sort the parameter names by character code point in ascending order.

      2. URI encode the parameter name and values according to the following rules:

        • Do not URI encode any of the unreserved characters that RFC 3986 defines.

          These unreserved characters are A-Z, a-z, 0-9, hyphen ( - ), underscore (_ ), period ( . ), and tilde ( ~ ).

        • Percent encode all other characters with %XY, where X and Y are hex characters 0-9 and uppercase A-F.

        • Percent encode extended UTF-8 characters in the form %XY%ZA....

        • Percent encode the space character as %20 (and not +, as common encoding schemes do).

        [Note] Note

        Currently all AWS service parameter names use unreserved characters, so you don't need to encode them. However, you might want to include code to handle parameter names that use reserved characters, for possible future use.

      3. Separate the encoded parameter names from their encoded values with the equals sign ( = ) (ASCII character 61), even if the parameter value is empty.

      4. Separate the name-value pairs with an ampersand ( & ) (ASCII code 38).

    4. Add the canonical headers, followed by a newline character. The canonical headers consist of a list of all the HTTP headers that you are including with the signed request.

      At a minimum, you must include the host header. Standard headers like content-type are optional.

      Example canonical headers

      host:ats.us-west-1.amazonaws.com\n
      x-amz-date: 20171113T030840Z\n
                    
    5. Add the signed headers, followed by a newline character. This value is the list of headers that you included in the canonical headers. By adding this list of headers, you tell AWS which headers in the request are part of the signing process and which ones AWS can ignore (for example, any additional headers added by a proxy) for purposes of validating the request.

      The host header must be included as a signed header. If you include a date or x-amz-date header, you must also include that header in the list of signed headers.

      Example signed headers

      host;x-amz-date\n
    6. Use a hash (digest) function like SHA256 to create a hashed value from the payload in the body of the HTTP or HTTPS request. Alexa Top Sites doesn't include any payload, so it's SHA256 of an empty string.

      Example hashed payload

      e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    7. To construct the finished canonical request, combine all the components from each step as a single string. As noted, each component ends with a newline character.

      Example canonical request (based on values from previous steps)

      GET
      /api
      Action=TopSites&CountryCode=US&ResponseGroup=Rank
      host:ats.us-west-1.amazonaws.com
      x-amz-date:20171113T030840Z
      
      host;x-amz-date
      e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
                    
    8. Create a digest (hash) of the canonical request with the same algorithm that you used to hash the payload.

      Example hashed canonical request.

      e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  2. Create the string to sign according to the following pseudo-grammar (the "\n" represents an ASCII newline).

    StringToSign =
        Algorithm + \n +
        RequestDateTime + \n +
        CredentialScope + \n +
        HashedCanonicalRequest <from the preceding step>
               
    1. Start with the algorithm designation, followed by a newline character. This value is the hashing algorithm that you use to calculate the digests in the canonical request. For SHA256, AWS4-HMAC-SHA256 is the algorithm.

      AWS4-HMAC-SHA256\n
    2. Append the request date value, followed by a newline character. The date is specified with ISO8601 basic format in the x-amz-date header in the format YYYYMMDD'T'HHMMSS'Z'. This value must match the value you used in any previous steps.

      20171113T030840Z\n
    3. Append the credential scope value, followed by a newline character. This value is a string that includes the date, the region you are targeting, the service you are requesting, and a termination string ("aws4_request") in lowercase characters. The region and service name strings must be UTF-8 encoded.

      20171113/us-west-1/AlexaTopSites/aws4_request\n
    4. Append the hash of the canonical request that you created in the previous step. This value is not followed by a newline character. The hashed canonical request must be lowercase base-16 encoded, as defined by Section 8 of RFC 4648.

      e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  3. Using the AWS secret access key, derive a signing key and then use that signing key and the string sto sign created in the previous step

    For more information, go to Calculate the signature for AWS Signature Version 4.

    To calculate a signature

    1. Derive your signing key. To do this, use your secret access key to create a series of hash-based message authentication codes (HMACs). This is shown in the following pseudocode, where HMAC(key, data) represents an HMAC-SHA256 function that returns output in binary format. The result of each hash function becomes input for the next one.

      Pseudocode for deriving a signing key

      kSecret = your secret access key
      kDate = HMAC("AWS4" + kSecret, "20171113")
      kRegion = HMAC(kDate, "us-west-1")
      kService = HMAC(kRegion, "AlexaTopSites")
      kSigning = HMAC(kService, "aws4_request")
                   
    2. Calculate the signature. To do this, use the signing key that you derived and the string to sign as inputs to the keyed hash function. After you calculate the signature, convert the binary value to a hexadecimal representation.

      signature = HexEncode(HMAC(derived signing key, string to sign))\n
  4. Add the resulting signature to the HTTP request in the Authorization request header.

    The following pseudocode shows the construction of the Authorization header.

    Authorization: algorithm Credential=access key ID/credential scope, SignedHeaders=SignedHeaders, Signature=signature

    The following example shows a finished Authorization header.

    Authorization: AWS4-HMAC-SHA256 Credential=<IAM_ACCESS_KEY>/20171113/us-west-1/AlexaTopSites/aws4_request, SignedHeaders=host;x-amz-date, Signature=203c25d22a436b5283917b38911cc8f87deb4d8ed406f197efc4d3a497972ee1