

# AWS Signature Version 4 for API requests
<a name="reference_sigv"></a>

**Important**  
If you use an AWS SDK (see [Sample Code and Libraries](https://aws.amazon.com/developer/)) or AWS Command Line Interface (AWS CLI) tool to send API requests to AWS, you can skip the signature process, as the SDK and CLI clients authenticate your requests by using the access keys that you provide. Unless you have a good reason not to, we recommend that you always use an SDK or the CLI.  
In Regions that support multiple signature versions, manually signing requests means you must specify which signature version to use. When you supply requests to Multi-Region Access Points, SDKs and the CLI automatically switch to using Signature Version 4A without additional configuration.

Authentication information that you send in a request must include a signature. AWS Signature Version 4 (SigV4) is the AWS signing protocol for adding authentication information to AWS API requests.

You don't use your secret access key to sign API requests. Instead, you use the SigV4 signing process. Signing requests involves:

1. Creating a canonical request based on the request details.

1. Calculating a signature using your AWS credentials.

1. Adding this signature to the request as an Authorization header.

AWS then replicates this process and verifies the signature, granting or denying access accordingly.

Symmetric SigV4 requires you to derive a key that is scoped to a single AWS service, in a single AWS region, on a particular day. This makes the key and calculated signature different for each region, meaning you must know the region the signature is destined for.

Asymmetric Signature Version 4 (SigV4a) is an extension that supports signing with a new algorithm, and generating individual signatures that are verifiable in more than one AWS region. With SigV4a, you can sign a request for multiple regions, with seamless routing and failover between regions. When you use the AWS SDK or AWS CLI to invoke functionality that requires multi-region signing, the signature type is automatically changed to use SigV4a. For details, see [How AWS SigV4a works](#how-sigv4a-works).

## How AWS SigV4 works
<a name="how-aws-signing-works"></a>

The following steps describe the general process of computing a signature with SigV4:

1. The **string to sign** depends on the request type. For example, when you use the HTTP Authorization header or the query parameters for authentication, you use a combination of request elements to create the string to sign. For an HTTP POST request, the `POST` policy in the request is the string you sign.

1. The **signing key** is a series of calculations, with the result of each step fed into the next. The final step is the signing key.

1. When an AWS service receives an authenticated request, it recreates the **signature** using the authentication information contained in the request. If the signatures match, the service processes the request. Otherwise, it rejects the request.

For more information, see [Elements of an AWS API request signature](reference_sigv-signing-elements.md).

## How AWS SigV4a works
<a name="how-sigv4a-works"></a>

SigV4a uses asymmetric signatures based on public-private key cryptography. SigV4a goes through a similar scoped credentials derivation process as SigV4, except SigV4a uses the same key to sign all requests without needing to derive a distinct signing key based on the date, service, and region. An [Elliptic Curve Digital Signature Algorithm](https://csrc.nist.gov/glossary/term/ecdsa) (ECDSA) keypair can be derived from your existing AWS secret access key.

The system uses asymmetric cryptography to verify multi-region signatures, so that AWS only needs to store your public keys. Public keys are not secret and can't be used to sign requests. Asymmetric signatures are required for multi-region API requests, such as with Amazon S3 Multi-Region Access Points.

The following steps describe the general process of computing a signature with SigV4a:

1. The **string to sign** depends on the request type. For example, when you use the HTTP Authorization header or the query parameters for authentication, you use a combination of request elements to create the string to sign. For an HTTP POST request, the `POST` policy in the request is the string you sign.

1. The **signing key** is derived from an AWS secret access key through a series of calculations, with the result of each step fed into the next. The final step produces the keypair.

1. When an AWS service receives a request signed with SigV4a, AWS verifies the signature using only the public half of the keypair. If the signature is valid, the request is authenticated and the service processes the request. Requests with invalid signatures are rejected.

For more information about SigV4a for multi-Region API requests, see the [sigv4a-signing-examples](https://github.com/aws-samples/sigv4a-signing-examples) project on GitHub.

## When to sign requests
<a name="when-do-you-need-to-sign"></a>

When you write custom code that sends API requests to AWS, you must include code that signs the requests. You might write custom code because:
+ You are working with a programming language for which there is no AWS SDK.
+ You need complete control over how requests are sent to AWS.

While API requests authenticate access with AWS SigV4, AWS SDKs and the AWS CLI authenticate your requests by using the access keys that you provide. For more information about authenticating with AWS SDKs and the AWS CLI, see [Additional resources](#reference_aws-signing-resources).

## Why requests are signed
<a name="why-requests-are-signed"></a>

The signing process helps secure requests in the following ways:
+ **Verify the identity of the requester**

  Authenticated requests require a signature that you create by using your access keys (access key ID, secret access key). If you are using temporary security credentials, the signature calculations also require a security token. For more information, see [AWS security credentials programmatic access](security-creds-programmatic-access.md).
+ **Protect data in transit**

  To prevent tampering with a request while it's in transit, some of the request elements are used to calculate a hash (digest) of the request, and the resulting hash value is included as part of the request. When an AWS service receives the request, it uses the same information to calculate a hash and matches it against the hash value in your request. If the values don't match, AWS denies the request.
+ **Protect against potential replay attacks**

  In most cases, a request must reach AWS within five minutes of the time stamp in the request. Otherwise, AWS denies the request.

AWS SigV4 can be expressed in the HTTP Authorization header or as a query string in the URL. For more information, see [Authentication methods](reference_sigv-authentication-methods.md).

## Additional resources
<a name="reference_aws-signing-resources"></a>
+ For more information about the SigV4 signing process for different services, see [Request signature examples](reference_sigv-examples.md).
+ To configure credentials for programmatic access for the AWS CLI, see [Authentication and access credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html) in the *AWS Command Line Interface User Guide*.
+ The AWS SDKs include source code on GitHub for signing AWS API requests. For code samples, see [Example projects in AWS samples repository](reference_sigv-examples.md#signature-v4-examples-sdk).
  + AWS SDK for .NET – [AWS4Signer.cs](https://github.com/aws/aws-sdk-net/blob/master/sdk/src/Core/Amazon.Runtime/Internal/Auth/AWS4Signer.cs)
  + AWS SDK for C\$1\$1 – [AWSAuthV4Signer.cpp](https://github.com/aws/aws-sdk-cpp/blob/main/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp)
  + AWS SDK for Go – [sigv4.go](https://github.com/aws/smithy-go/blob/a4c9efcda6aa54c75d1a130d1320a2709eebf51d/aws-http-auth/sigv4/sigv4.go)
  + AWS SDK for Java – [BaseAws4Signer.java](https://github.com/aws/aws-sdk-java-v2/blob/master/core/auth/src/main/java/software/amazon/awssdk/auth/signer/internal/BaseAws4Signer.java)
  + AWS SDK for JavaScript – [signature-v4](https://github.com/smithy-lang/smithy-typescript/tree/main/packages/signature-v4)
  + AWS SDK for PHP – [SignatureV4.php](https://github.com/aws/aws-sdk-php/blob/master/src/Signature/SignatureV4.php)
  + AWS SDK for Python (Boto) – [signers.py](https://github.com/boto/botocore/blob/develop/botocore/signers.py)
  + AWS SDK for Ruby – [signer.rb](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sigv4/lib/aws-sigv4/signer.rb)

# Elements of an AWS API request signature
<a name="reference_sigv-signing-elements"></a>

**Important**  
Unless you are using the AWS SDKs or CLI, you must write code to calculate signatures that provide authentication information in your requests. Signature calculation in AWS Signature Version 4 can be a complex undertaking, and we recommend that you use the AWS SDKs or CLI whenever possible.

Each HTTP/HTTPS request that uses Signature Version 4 signing must contain these elements.

**Topics**
+ [

## Endpoint specification
](#endpoint-specification)
+ [

## Action
](#action)
+ [

## Action parameters
](#parameters)
+ [

## Date
](#date)
+ [

## Authentication information
](#authentication)

## Endpoint specification
<a name="endpoint-specification"></a>

Specifies the DNS name of the endpoint to which you send the request. This name usually contains the service code and the Region. For example, the endpoint for Amazon DynamoDB in the `us-east-1` Region is `dynamodb.us-east-1.amazonaws.com`.

For HTTP/1.1 requests, you must include the `Host` header. For HTTP/2 requests, you can include the `:authority` header or the `Host` header. Use only the `:authority` header for compliance with the HTTP/2 specification. Not all services support HTTP/2 requests.

For the endpoints supported by each service, see [Service endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/aws-service-information.html) in the *AWS General Reference*.

## Action
<a name="action"></a>

Specifies an API action for the service. For example, the DynamoDB `CreateTable` action or the Amazon EC2 `DescribeInstances` action.

For the actions supported by each service, see the [Service Authorization Reference](https://docs.aws.amazon.com//service-authorization/latest/reference/reference.html).

## Action parameters
<a name="parameters"></a>

Specifies the parameters for the action specified in the request. Each AWS API action has a set of required and optional parameters. The API version is usually a required parameter.

For the parameters supported by an API action, see the API Reference for the service.

## Date
<a name="date"></a>

Specifies the date and time of the request. Including the date and time in a request helps prevent third parties from intercepting your request and resubmitting it later. The date that you specify in the credential scope must match the date of your request.

The time stamp must be in UTC and use the following ISO 8601 format: *YYYYMMDD*T*HHMMSS*Z. For example, `20220830T123600Z`. Do not include milliseconds in the time stamp.

You can use a `date` or an `x-amz-date` header, or include `x-amz-date` as a query parameter. If we can't find an `x-amz-date` header, then we look for a `date` header.

## Authentication information
<a name="authentication"></a>

Each request that you send must include the following information. AWS uses this information to ensure the validity and authenticity of the request.
+ Algorithm – The algorithm that you're using as part of the signing process. 
  + SigV4 – Use `AWS4-HMAC-SHA256` to specify Signature Version 4 with the `HMAC-SHA256` hash algorithm. 
  + SigV4a – Use `AWS4-ECDSA-P256-SHA256` to specify the `ECDSA-P256-SHA-256` hash algorithm.
+ Credential – A string that is formed by concatenating your access key ID and your credential scope components.
  + SigV4 – Credential scope includes your access key ID, the date in *YYYYMMDD* format, the Region code, the service code, and the `aws4_request` termination string, separated by slashes (/). The Region code, service code, and termination string must use lowercase characters.

    ```
    AKIAIOSFODNN7EXAMPLE/YYYYMMDD/region/service/aws4_request
    ```
  + SigV4a – Credential scope includes the date in YYYYMMDD format, the service name, and the `aws4_request` termination string, separated by slashes (/). Note that credential scope does not include the region as the region is covered in a separate header `X-Amz-Region-Set`.

    ```
    AKIAIOSFODNN7EXAMPLE/YYYYMMDD/service/aws4_request
    ```
+ Signed headers – The HTTP headers to include in the signature, separated by semicolons (;). For example, `host;x-amz-date`.

  For SigV4a, you must include a region set header that specifies the set of regions the request will be valid in. The header `X-Amz-Region-Set` is specified as a list of comma separated values. The following example shows a region header that allows a request to be made in both us-east-1 and us-west-1 regions.

  ```
  X-Amz-Region-Set=us-east-1,us-west-1
  ```

  You can use wildcards (\$1) in regions to specify multiple regions. In the following example, the header allows a request to be made in both us-west-1 and us-west-2.

  ```
  X-Amz-Region-Set=us-west-*
  ```
+ Signature – A hexadecimal-encoded string that represents the calculated signature. You must calculate the signature using the algorithm that you specified in the `Algorithm` parameter. 

For more information, see [Authentication methods](reference_sigv-authentication-methods.md)

# Authentication methods
<a name="reference_sigv-authentication-methods"></a>

**Important**  
Unless you are using the AWS SDKs or CLI, you must write code to calculate signatures that provide authentication information in your requests. Signature calculation in AWS Signature Version 4 can be a complex undertaking, and we recommend that you use the AWS SDKs or CLI whenever possible.

You can express authentication information by using one of the following methods.

## HTTP authorization header
<a name="aws-signing-authentication-methods-http"></a>

The HTTP `Authorization` header is the most common method of authenticating a request. All REST API operations (except for browser-based uploads using `POST` requests) require this header.

The following examples show the `Authorization` header value for SigV4 and SigV4a. Line breaks are added to this example for readability. In your code, the header must be a continuous string. There is no comma between the algorithm and Credential, but the other elements must be separated by commas.

**Example SigV4**  

```
Authorization: AWS4-HMAC-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, 
SignedHeaders=host;range;x-amz-date, 
Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
```

**Example SigV4a**  

```
Authorization: AWS4-ECDSA-P256-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20130524/s3/aws4_request, 
SignedHeaders=host;range;x-amz-date;x-amz-region-set,
Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
```

The following table describes the various components of the Authorization header value in the preceding example:


| Component | Description | 
| --- | --- | 
|  Authorization  | The algorithm that was used to calculate the signature. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-authentication-methods.html)  | 
|  Credential  |  Your access key ID and the scope information. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-authentication-methods.html) The <date> value is specified using YYYYMMDD format. <aws-service> value is S3 when sending request to Amazon S3.  | 
|  SignedHeaders  |   A semicolon-separated list of request headers that you used to compute Signature. The list includes header names only, and the header names must be in lowercase. For example: `host;range;x-amz-date` For SigV4a, you must include a region set header that specifies the set of regions the request will be valid in. The header X-Amz-Region-Set is specified as a list of comma separated values.  | 
|  Signature  |  The 256-bit signature expressed as 64 lowercase hexadecimal characters. For example:`fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024` Note that the signature calculations vary depending on the option you choose to transfer the payload.  | 

## Query string parameters
<a name="aws-signing-authentication-methods-query"></a>

You can use a query string to express a request entirely in a URL. In this case, you use query parameters to provide request information, including the authentication information. Because the request signature is part of the URL, this type of URL is often referred to as a presigned URL. You can use presigned URLs to embed clickable links in HTML, which can be valid for up to seven days. For more information, see [Authenticating Requests: Using Query Parameters (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html) in the *Amazon S3 API Reference*.

The following examples show presigned URLs for SigV4 and SigV4a. Line breaks are added to this example for readability:

**Example SigV4**  

```
https://s3.amazonaws.com/amzn-s3-demo-bucket/test.txt ?
X-Amz-Algorithm=AWS4-HMAC-SHA256 &
X-Amz-Credential=<your-access-key-id>/20130721/<region>/s3/aws4_request &
X-Amz-Date=20130721T201207Z &
X-Amz-Expires=86400 &
X-Amz-SignedHeaders=host &X-Amz-Signature=<signature-value>
```

**Example SigV4a**  

```
http://s3.amazonaws.com/amzn-s3-demo-bucket/test.txt ?
X-Amz-Algorithm=AWS4-ECDSA-P256-SHA256 &
X-Amz-Credential=<your-access-key-id>/20240721/s3/aws4_request &
X-amz-Region-Set=<regionset> &
X-Amz-Date=20240721T201207Z &
X-Amz-Expires=86400 &
X-Amz-SignedHeaders=host;x-amz-region-set &
X-Amz-Signature=<signature-value>
```

**Note**  
The `X-Amz-Credential` value in the URL shows the "/" character only for readability. In practice, it should be encoded as %2F. For example:  
`&X-Amz-Credential=<your-access-key-id>%2F20130721%2Fus-east-1%2Fs3%2Faws4_request`

The following table describes the query parameters in the URL that provide authentication information.


| Query string parameter name | Description | 
| --- | --- | 
|  X-Amz-Algorithm  |  The version of AWS signature and the algorithm that you used to calculate the signature. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-authentication-methods.html)  | 
|  X-Amz-Credential  |  In addition to your access key ID, this parameter also provides scope for which the signature is valid. This value must match the scope you use in signature calculations, discussed in the following section. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-authentication-methods.html) For a list of AWS regional strings, see [Regional Endpoints](https://docs.aws.amazon.com//general/latest/gr/rande.html#regional-endpoints) in the *AWS General Reference*.  | 
|  X-Amz-Region-Set  |  The set of regions the request will be valid in. The header x-amz-region-set is specified as a list of comma separated values.  | 
|  X-Amz-Date  |  The date and time format must follow the ISO 8601 standard, and must be formatted with the `yyyyMMddTHHmmssZ` format. For example if the date and time was "08/01/2016 15:32:41.982-700" then it must first be converted to UTC (Coordinated Universal Time) and then submitted as "20160801T223241Z".  | 
|  X-Amz-Expires  |  Provides the time period, in seconds, for which the generated presigned URL is valid. For example, 86400 (24 hours). This value is an integer. The minimum value you can set is 1, and the maximum is 604800 (seven days).A presigned URL can be valid for a maximum of seven days because the signing key you use in signature calculation is valid for up to seven days.  | 
|  X-Amz-SignedHeaders  |  Lists the headers that you used to calculate the signature. The following headers are required in the signature calculations: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-authentication-methods.html) For added security, you should sign all the request headers that you plan to include in your request.  | 
|  X-Amz-Signature  |  Provides the signature to authenticate your request. This signature must match the signature the service calculates; otherwise, the service denies the request. For example, `733255ef022bec3f2a8701cd61d4b371f3f28c9f193a1f02279211d48d5193d7` Signature calculations are described in the following section.  | 
|  X-Amz-Security-Token  |  Optional credential parameter if using credentials sourced from the STS service.  | 

# Create a signed AWS API request
<a name="reference_sigv-create-signed-request"></a>

**Important**  
If you use an AWS SDK (see [Sample Code and Libraries](https://aws.amazon.com/developer/)) or AWS Command Line Interface (AWS CLI) tool to send API requests to AWS, you can skip this section because the SDK and CLI clients authenticate your requests by using the access keys that you provide. Unless you have a good reason not to, we recommend that you always use an SDK or the CLI.  
In Regions that support multiple signature versions, manually signing requests means you must specify which signature version is used. When you supply requests to Multi-Region Access Points, SDKs and the CLI automatically switch to using Signature Version 4A without additional configuration.

You can use the AWS SigV4 signing protocol to create a signed request for AWS API requests.

1. Creating a canonical request based on the request details.

1. Calculating a signature using your AWS credentials.

1. Adding this signature to the request as an Authorization header.

AWS then replicates this process and verifies the signature, granting or denying access accordingly.

To see how you can use AWS SigV4 to sign API requests, see [Request signature examples](reference_sigv-examples.md).

The following table describes the functions that are used in the process of creating a signed request. You need to implement code for these functions. For more information, see the [code examples in the AWS SDKs](reference_sigv.md#reference_aws-signing-resources).


| Function | Description | 
| --- | --- | 
|  `Lowercase()`  |  Convert the string to lowercase.  | 
|  `Hex()`  |  Lowercase base 16 encoding.  | 
|  `SHA256Hash()`  |  Secure Hash Algorithm (SHA) cryptographic hash function.  | 
|  `HMAC-SHA256()`  |  Computes HMAC by using the SHA256 algorithm with the signing key provided. This is the final signature when you sign with SigV4.  | 
|  `ECDSA-Sign`  |  Elliptic Curve Digital Signature Algorithm (ECDSA) signature computed by using asymmetric signatures based on public-private key cryptography.   | 
|  `KDF(K, Label, Context, L)`  |  A NIST SP800-108 KDF in Counter Mode using the PRF function HMAC-SHA256 as defined in [NIST SP 800-108r1](https://doi.org/10.6028/NIST.SP.800-108r1-upd1).  | 
|  `Oct2Int(byte[ ])`  |  An octet to integer function as described in ANSI X9.62.  | 
|  `Trim()`  |  Remove any leading or trailing whitespace.  | 
|  `UriEncode()`  |  URI encode every byte. UriEncode() must enforce the following rules: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html)  The standard UriEncode functions provided by your development platform may not work because of differences in implementation and related ambiguity in the underlying RFCs. We recommend that you write your own custom UriEncode function to ensure that your encoding will work.  To see an example of a UriEncode function in Java, see [Java Utilities](https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/util/SdkHttpUtils.java#L66) on the GitHub website.  | 

**Note**  
When signing your requests, you can use either AWS SigV4 or AWS SigV4a. The key difference between the two is determined by how the signature is calculated. With SigV4a, the region set is included in the string to sign, but is not part of the credential derivation step.

## Signing requests with temporary security credentials
<a name="temporary-security-credentials"></a>

Instead of using long-term credentials to sign a request, you can use temporary security credentials provided by AWS Security Token Service (AWS STS).

When you use temporary security credentials, you must add `X-Amz-Security-Token` to the Authorization header or include it in the query string to hold the session token. Some services require that you add `X-Amz-Security-Token` to the canonical request. Other services require only that you add `X-Amz-Security-Token` at the end, after you calculate the signature. Check the documentation for each AWS service for specific requirements.

## Summary of signing steps
<a name="create-signed-request-steps"></a>

**Create a canonical request**  
Arrange the contents of your request (host, action, headers, etc.) into a standard canonical format. The canonical request is one of the inputs used to create the string to sign. For details on creating the canonical request, see [Elements of an AWS API request signature](reference_sigv-signing-elements.md).

**Create a hash of the canonical request**  
Hash the canonical request using the same algorithm that you used to create the hash of the payload. The hash of the canonical request is a string of lowercase hexadecimal characters.

**Create a string to sign**  
Create a string to sign with the canonical request and extra information such as the algorithm, request date, credential scope, and the hash of the canonical request.

**Derive a signing key**  
Use the secret access key to derive the key used to sign the request.

**Calculate the signature**  
Perform a keyed hash operation on the string to sign using the derived signing key as the hash key.

**Add the signature to the request**  
Add the calculated signature to an HTTP header or to the query string of the request.

## Create a canonical request
<a name="create-canonical-request"></a>

To create a canonical request, concatenate the following strings, separated by newline characters. This helps ensure that the signature that you calculate can match the signature that AWS calculates.

```
<HTTPMethod>\n
<CanonicalURI>\n
<CanonicalQueryString>\n
<CanonicalHeaders>\n
<SignedHeaders>\n
<HashedPayload>
```
+ *HTTPMethod* – The HTTP method, such as `GET`, `PUT`, `HEAD`, and `DELETE`.
+ *CanonicalUri* – The URI-encoded version of the absolute path component URI, starting with the `/` that follows the domain name and up to the end of the string or to the question mark character (`?`) if you have query string parameters. If the absolute path is empty, use a forward slash character (`/`). The URI in the following example, `/amzn-s3-demo-bucket/myphoto.jpg`, is the absolute path and you don't encode the `/` in the absolute path:

  ```
  http://s3.amazonaws.com/amzn-s3-demo-bucket/myphoto.jpg
  ```
+ *CanonicalQueryString* – The URI-encoded query string parameters. You URI-encode each name and value individually. You must also sort the parameters in the canonical query string alphabetically by key name. The sorting occurs after encoding. The query string in the following URI example is:

  ```
  http://s3.amazonaws.com/amzn-s3-demo-bucket?prefix=somePrefix&marker=someMarker&max-keys=2
  ```

  The canonical query string is as follows (line breaks are added to this example for readability):

  ```
  UriEncode("marker")+"="+UriEncode("someMarker")+"&"+
  UriEncode("max-keys")+"="+UriEncode("20") + "&" +
  UriEncode("prefix")+"="+UriEncode("somePrefix")
  ```

  When a request targets a subresource, the corresponding query parameter value will be an empty string (`""`). For example, the following URI identifies the `ACL` subresource on the `amzn-s3-demo-bucket` bucket:

   

  ```
  http://s3.amazonaws.com/amzn-s3-demo-bucket?acl
  ```

  In this case, the CanonicalQueryString would be:

   

  ```
  UriEncode("acl") + "=" + ""
  ```

  If the URI does not include a `?`, there is no query string in the request, and you set the canonical query string to an empty string (`""`). You will still need to include the newline character (`"\n"`).
+ *CanonicalHeaders* – A list of request headers with their values. Individual header name and value pairs are separated by the newline character (`"\n"`). The following is an example of a CanonicalHeader:

  ```
  Lowercase(<HeaderName1>)+":"+Trim(<value>)+"\n"
  Lowercase(<HeaderName2>)+":"+Trim(<value>)+"\n"
  ...
  Lowercase(<HeaderNameN>)+":"+Trim(<value>)+"\n"
  ```

  CanonicalHeaders list must include the following:
  + HTTP `host` header.
  + If the `Content-Type` header is present in the request, you must add it to the *CanonicalHeaders* list. 
  + Any `x-amz-*` headers that you plan to include in your request must also be added. For example, if you are using temporary security credentials, you need to include `x-amz-security-token` in your request. You must add this header in the list of *CanonicalHeaders*.
  + For SigV4a, you must include a region set header that specifies the set of regions the request will be valid in. The header `X-Amz-Region-Set` is specified as a list of comma separated values. The following example shows a region header that allows a request to be made in both us-east-1 and us-west-1 regions.

    `X-Amz-Region-Set=us-east-1,us-west-1 `

    You can use wildcards (\$1) in regions to specify multiple regions. In the following example, the header allows a request to be made in both us-west-1 and us-west-2.

    `X-Amz-Region-Set=us-west-*`
**Note**  
The `x-amz-content-sha256` header is required for Amazon S3 AWS requests. It provides a hash of the request payload. If there is no payload, you must provide the hash of an empty string.

  Each header name must:
  + use lowercase characters.
  + appear in alphabetical order.
  + be followed by a colon (`:`).

  For values, you must:
  + trim any leading or trailing spaces.
  + convert sequential spaces to a single space.
  + separate the values for a multi-value header using commas.
  + You must include the host header (HTTP/1.1) or the :authority header (HTTP/2), and any `x-amz-*` headers in the signature. You can optionally include other standard headers in the signature, such as content-type.

  The `Lowercase()` and `Trim()` functions used in this example are described in the preceding section.

  The following is an example `CanonicalHeaders` string. The header names are in lowercase and sorted.

   

  ```
  host:s3.amazonaws.com
  x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  x-amz-date:20130708T220855Z
  ```

   
**Note**  
For the purpose of calculating an authorization signature, only the host and any `x-amz-*` headers are required; however, in order to prevent data tampering, you should consider including additional headers in the signature calculation.  
Do not include hop-by-hop headers that are frequently altered during transit across a complex system. This includes all volatile transport headers that are mutated by proxies, load balancers, and the nodes in a distributed system, including `connection`, `x-amzn-trace-id`, `user-agent`, `keep-alive`, `transfer-encoding`, `TE`, `trailer`, `upgrade`, `proxy-authorization`, and `proxy-authenticate`.
+ *SignedHeaders* – An alphabetically sorted, semicolon-separated list of lowercase request header names. The request headers in the list are the same headers that you included in the `CanonicalHeaders` string. For the previous example, the value of *SignedHeaders* would be as follows:

  ```
  host;x-amz-content-sha256;x-amz-date
  ```
+ *HashedPayload* – A string created using the payload in the body of the HTTP request as input to a hash function. This string uses lowercase hexadecimal characters.

  ```
  Hex(SHA256Hash(<payload>>))
  ```

  If there is no payload in the request, you compute a hash of the empty string, such as when you retrieve an object by using a `GET` request, there is nothing in the payload.

  ```
  Hex(SHA256Hash(""))
  ```
**Note**  
For Amazon S3, include the literal string `UNSIGNED-PAYLOAD` when constructing a canonical request, and set the same value as the `x-amz-content-sha256` header value when sending the request.  
`Hex(SHA256Hash("UNSIGNED-PAYLOAD"))`

## Create a hash of the canonical request
<a name="create-canonical-request-hash"></a>

Create a hash (digest) of the canonical request using the same algorithm that you used to create the hash of the payload. The hash of the canonical request is a string of lowercase hexadecimal characters.

## Create a string to sign
<a name="create-string-to-sign"></a>

To create a string to sign, concatenate the following strings, separated by newline characters. Do not end this string with a newline character.

```
Algorithm \n
RequestDateTime \n
CredentialScope  \n
HashedCanonicalRequest
```
+ *Algorithm* – The algorithm used to create the hash of the canonical request.
  + SigV4 – Use `AWS4-HMAC-SHA256` to specify the `HMAC-SHA256` hash algorithm. 
  + SigV4a – Use `AWS4-ECDSA-P256-SHA256` to specify the `ECDSA-P256-SHA-256` hash algorithm. 
+ *RequestDateTime* – The date and time used in the credential scope. This value is the current UTC time in ISO 8601 format (for example, `20130524T000000Z`).
+ *CredentialScope* – The credential scope, which restricts the resulting signature to the specified Region and service.
  + SigV4 – Credentials include your access key ID, the date in `YYYYMMDD` format, the Region code, the service code, and the `aws4_request` termination string, separated by slashes (/). The Region code, service code, and termination string must use lowercase characters. The string has the following format: `YYYYMMDD/region/service/aws4_request`.
  + SigV4a – Credentials include the date in `YYYYMMDD` format, the service name, and the `aws4_request` termination string, separated by slashes (/). Note that credential scope does not include the region as the region is covered in a separate header `X-Amz-Region-Set`. The string has the following format: `YYYYMMDD/service/aws4_request`.
+ *HashedCanonicalRequest* – The hash of the canonical request, calculated in the previous step.

The following is an example string to sign.

```
"<Algorithm>" + "\n" +
timeStampISO8601Format + "\n" +
<Scope> + "\n" +
Hex(<Algorithm>(<CanonicalRequest>))
```

## Derive a signing key
<a name="derive-signing-key"></a>

To derive a signing key, choose one of the following processes to compute a signing key for either SigV4 or SigV4a.

### Deriving a signing key for SigV4
<a name="derive-signing-key-sigv4"></a>

To derive a signing key for SigV4, perform a succession of keyed hash operations (HMAC) on the request date, Region, and service, with your AWS secret access key as the key for the initial hashing operation.

For each step, call the hash function with the required key and data. The result of each call to the hash function becomes the input for the next call to the hash function.

The following example shows how you derive the `SigningKey` used in the next section of this procedure, showing the order in which your input is concatenated and hashed. `HMAC-SHA256` is the hash function used to hash the data as shown.

```
DateKey = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>")
DateRegionKey = HMAC-SHA256(<DateKey>, "<aws-region>")
DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<aws-service>")
SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")
```

**Required input**
+ `Key` – A string that contains your secret access key.
+ `Date` – A string that contains the date used in the credential scope, in the format *YYYYMMDD*.
+ `Region` – A string that contains the Region code (for example, `us-east-1`).

  For a list of Region strings, see [Regional Endpoints](https://docs.aws.amazon.com//general/latest/gr/rande.html#regional-endpoints) in the *AWS General Reference*.
+ `Service` – A string that contains the service code (for example, `ec2`).
+ The string to sign that you created in the previous step.

**To derive a signing key for SigV4**

1. Concatenate `"AWS4"` and the secret access key. Call the hash function with the concatenated string as the key and the date string as the data.

   ```
   DateKey = hash("AWS4" + Key, Date)
   ```

1. Call the hash function with the result of the previous call as the key and the Region string as the data.

   ```
   DateRegionKey = hash(kDate, Region)
   ```

1. Call the hash function with the result of the previous call as the key and the service string as the data.

   The service code is defined by the service. You can use [get-products](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/pricing/get-products.html) in the *AWS Pricing CLI* to return the service code for a service.

   ```
   DateRegionServiceKey = hash(kRegion, Service)
   ```

1. Call the hash function with the result of the previous call as the key and "aws4\$1request" as the data.

   ```
   SigningKey = hash(kService, "aws4_request")
   ```

### Deriving a signing key for SigV4a
<a name="derive-signing-key-sigv4a"></a>

To create a signing key for SigV4a, use the following process to derive a key pair from the secret access key. For an example of an implementation of this derivation, see the [C99 library implementation of AWS client-side authentication](https://github.com/awslabs/aws-c-auth/blob/e8360a65e0f3337d4ac827945e00c3b55a641a5f/source/key_derivation.c#L291.) 

```
n = [NIST P-256 elliptic curve group order]
G = [NIST P-256 elliptic curve base point]
label = "AWS4-ECDSA-P256-SHA256"

akid = [AWS access key ID as a UTF8 string]
sk = [AWS secret access Key as a UTF8 Base64 string]

input_key = "AWS4A" || sk
count = 1
while (counter != 255) {
  context = akid || counter // note: counter is one byte
  key = KDF(input_key, label, context, 256)
  c = Oct2Int(key)
  if (c > n - 2) {
    counter++
  } else {
    k = c + 1   // private key
    Q = k * G   // public key
  }
}

if (c < 255) {
  return [k, Q]
} else {
  return FAILURE
}
```

## Calculate the signature
<a name="calculate-signature"></a>

Once you have derived the signing key, calculate the signature to add to your request. This procedure varies based on the signature version you use.

**To calculate a signature for SigV4**

1. Call the hash function with the result of the previous call as the key and the **string to sign** as the data. Use the derived signing key as the hash key for this operation. The result is the signature as a binary value.

   ```
   signature = hash(SigningKey, string-to-sign)
   ```

1. Convert the signature from binary to hexadecimal representation, in lowercase characters.

**To calculate a signature for SigV4a**

1. Using the digital signing algorithm (ECDSA P-256), sign the **string to sign** you created in the previous step. The key used for this signature is the private asymmetric key derived from the secret access key as described above.

   ```
   signature = base16(ECDSA-Sign(k, string-to-sign))
   ```

1. Convert the signature from binary to hexadecimal representation, in lowercase characters.

## Add the signature to the request
<a name="add-signature-to-request"></a>

Add the calculated signature to your request.

**Example: Authorization header**  
**SigV4**  
The following example shows an `Authorization` header for the `DescribeInstances` action using AWS SigV4. For readability, this example is formatted with line breaks. In your code, this must be a continuous string. There is no comma between the algorithm and `Credential`. However, the other elements must be separated by commas.

```
Authorization: AWS4-HMAC-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request,
SignedHeaders=host;x-amz-date,
Signature=calculated-signature
```

**SigV4a**  
The following example shows an Authorization header for the `CreateBucket` action using AWS SigV4a. For readability, this example is formatted with line breaks. In your code, this must be a continuous string. There is no comma between the algorithm and Credential. However, the other elements must be separated by commas.

```
Authorization: AWS4-ECDSA-P256-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20220830/s3/aws4_request,
SignedHeaders=host;x-amz-date;x-amz-region-set,
Signature=calculated-signature
```

**Example: Request with authentication parameters in the query string**  
**SigV4**  
The following example shows a query for the `DescribeInstances` action using AWS SigV4 that includes the authentication information. For readability, this example is formatted with line breaks and is not URL encoded. In your code, the query string must be a continuous string that is URL encoded.

```
https://ec2.amazonaws.com/?
Action=DescribeInstances&
Version=2016-11-15&
X-Amz-Algorithm=AWS4-HMAC-SHA256&
X-Amz-Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request&
X-Amz-Date=20220830T123600Z&
X-Amz-SignedHeaders=host;x-amz-date&
X-Amz-Signature=calculated-signature
```

**SigV4a**  
The following example shows a query for the `CreateBucket` action using AWS SigV4a that includes the authentication information. For readability, this example is formatted with line breaks and is not URL encoded. In your code, the query string must be a continuous string that is URL encoded.

```
https://ec2.amazonaws.com/?
Action=CreateBucket&
Version=2016-11-15&
X-Amz-Algorithm=AWS4-ECDSA-P256-SHA256&
X-Amz-Credential=AKIAIOSFODNN7EXAMPLE/20220830/s3/aws4_request&
X-Amz-Region-Set=us-west-1&
X-Amz-Date=20220830T123600Z&
X-Amz-SignedHeaders=host;x-amz-date;x-amz-region-set&
X-Amz-Signature=calculated-signature
```

# Request signature examples
<a name="reference_sigv-examples"></a>

The following examples of AWS signing requests show you how you can use SigV4 to sign requests sent without the AWS SDK or AWS command line tool.

## Browser based Amazon S3 upload using HTTP POST
<a name="signature-v4-examples-s3-browser"></a>

 [Authenticating Requests: Browser-Based Uploads](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html) describes the signature and relevant information that Amazon S3 uses to calculate the signature upon receiving the request.

[Example: Browser-Based Upload using HTTP POST (Using AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html) provides more information with a sample POST policy and a form that you can use to upload a file. The example policy and fictitious credentials show you the workflow and resulting signature and policy hash.

## VPC Lattice authenticated requests
<a name="signature-v4-examples-lattice"></a>

 [Examples for Signature Version 4 (SigV4) authenticated requests](https://docs.aws.amazon.com/vpc-lattice/latest/ug/sigv4-authenticated-requests.html) provides Python and Java examples showing how you can perform request signing with and without custom interceptors.

## Using Signature Version 4 with Amazon Translate
<a name="signature-v4-examples-translate"></a>

 [Live Translations in the Metaverse](https://aws.amazon.com/blogs/spatial/live-translations-in-the-metaverse/) shows how to build an application that produces a near real-time translation solution. This speech-to-speech translator solution uses AWS SigV4 in event stream encoding to produce real-time transcriptions.

## Using Signature Version 4 with Neptune
<a name="signature-v4-examples-neptune"></a>

[Example: Connecting to Neptune Using Python with Signature Version 4 Signing](https://docs.aws.amazon.com/neptune/latest/userguide/iam-auth-connecting-python.html) shows how to make signed requests to Neptune using Python. This example includes variations for using an access key or temporary credentials.

## Signing HTTP requests to Amazon Glacier
<a name="signature-v4-examples-streaming-glacier"></a>

[Example Signature Calculation for Streaming API](https://docs.aws.amazon.com/amazonglacier/latest/dev/amazon-glacier-signing-requests.html) walks you through the details of creating a signature for Upload Archive (POST archive), one of the two streaming APIs in Amazon Glacier.

## Making HTTP Requests to Amazon SWF
<a name="signature-v4-examples-swf"></a>

[Making HTTP Requests to Amazon SWF](https://docs.aws.amazon.com/amazonswf/latest/developerguide/UsingJSON-swf.html#HTTPHeader) shows the header contents for a JSON request to Amazon SWF.

## Signature calculation for streaming APIs in Amazon OpenSearch Service
<a name="signature-v4-examples-open-search"></a>

[Signing an Amazon OpenSearch Service search request with AWS SDK for PHP Version 3](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/service_es-data-plane.html) includes an example of how to send signed HTTP requests to Amazon OpenSearch Service.

## Example projects in AWS samples repository
<a name="signature-v4-examples-sdk"></a>

The following example projects show how to sign requests to make Rest API requests to AWS services with common languages such as Python, Node.js, Java, C\$1, Go and Rust. 

### Signature Version 4a projects
<a name="signature-v4-examples-sigv4a"></a>

The [sigv4-signing-examples](https://github.com/aws-samples/sigv4-signing-examples) project provides examples of how to sign requests with SigV4 to make Rest API requests to AWS services with common languages such as Python, Node.js, Java, C\$1, Go and Rust.

The [sigv4a-signing-examples](https://github.com/aws-samples/sigv4a-signing-examples) project provides examples for signing multi-Region API requests, for example [ Multi-Region Access Points in Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiRegionAccessPoints.html).

### Publish to AWS IoT Core
<a name="signature-v4-examples-iot-python"></a>

[Python code to publish to AWS IoT Core using HTTPs protocol](https://github.com/aws-samples/aws-iot-core-python-node-sigv4-https) provides guidance on how to publish messages to AWS IoT Core using HTTPS protocol and AWS SigV4 authentication. It has two reference implementations - one in Python and other in NodeJs.

[.Net Framework application to publish to AWS IoT Core using HTTPs protocol](https://github.com/aws-samples/aws-iot-core-http-sigv4-dotnet-app) provides guidance on how to publish messages to AWS IoT Core using HTTPS protocol and AWS SigV4 authentication. This project also includes a .NET core equivalent implementation.

# Troubleshoot Signature Version 4 signing for AWS API requests
<a name="reference_sigv-troubleshooting"></a>

**Important**  
Unless you are using the AWS SDKs or CLI, you must write code to calculate signatures that provide authentication information in your requests. SigV4 signature calculation can be a complex undertaking, and we recommend that you use the AWS SDKs or CLI whenever possible.

When you develop code that creates a signed request, you might receive HTTP 403 `SignatureDoesNotMatch` from AWS services. These errors mean that the signature value in your HTTP request to AWS did not match the signature that the AWS service calculated. HTTP 401 `Unauthorized` errors return when permissions do not allow the caller to make the request.

API requests might return an error if:
+ The API request isn't signed and the API request uses IAM authentication.
+ The IAM credentials used to sign the request are incorrect or don't have permissions to invoke the API.
+ The signature of the signed API request doesn't match the signature that the AWS service calculated.
+ The API request header is incorrect.

**Note**  
Update your signing protocol from AWS Signature version 2 (SigV2) to AWS Signature version 4 (SigV4) before exploring other error solutions. Services, such as Amazon S3, and Regions no longer support SigV2 signing.

**Topics**
+ [

## Credential errors
](#signature-v4-troubleshooting-credential)
+ [

## Canonical request and signing string errors
](#signature-v4-troubleshooting-canonical-errors)
+ [

## Credential scope errors
](#signature-v4-troubleshooting-credential-scope)
+ [

## Key signing errors
](#signature-v4-troubleshooting-key-signing)

## Credential errors
<a name="signature-v4-troubleshooting-credential"></a>

Make sure that the API request is signed with SigV4. If the API request isn't signed, then you might receive the error: `Missing Authentication Token`. [Add the missing signature](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html#add-signature-to-request) and resend the request.

Verify that the authentication credentials for the access key and secret key are correct. If the access key is incorrect, then you might receive the error: `Unauthorized`. Make sure the entity used to sign the request is authorized to make the request. For details, see [Troubleshoot access denied error messages](troubleshoot_access-denied.md). 

## Canonical request and signing string errors
<a name="signature-v4-troubleshooting-canonical-errors"></a>

If you incorrectly calculated the canonical request in [Create a hash of the canonical request](reference_sigv-create-signed-request.md#create-canonical-request-hash) or [Create a string to sign](reference_sigv-create-signed-request.md#create-string-to-sign), the signature verification step performed by the service fails with the error message:

```
The request signature we calculated does not match the signature you provided
```

When the AWS service receives a signed request, it recalculates the signature. If there are differences in the values, then the signatures don’t match. Compare the canonical request and string to your signed request with the value in the error message. Modify the signing process if there are any differences.

**Note**  
You can also verify that you didn't send the request through a proxy that modifies the headers or the request.

**Example canonical request**  

```
GET                                                      -------- HTTP method
/                                                        -------- Path. For API stage endpoint, it should be /{stage-name}/{resource-path}
                                                         -------- Query string key-value pair. Leave it blank if the request doesn't have a query string.
content-type:application/json                            -------- Header key-value pair. One header per line.
host:0123456789.execute-api.us-east-1.amazonaws.com      -------- Host and x-amz-date are required headers for all signed requests.                       
x-amz-date:20220806T024003Z                              

content-type;host;x-amz-date                             -------- A list of signed headers
d167e99c53f15b0c105101d468ae35a3dc9187839ca081095e340f3649a04501        -------- Hash of the payload
```

To verify that the secret key matches the access key ID, you can test them with a known working implementation. For example, use an AWS SDK or the AWS CLI to make a request to AWS.

### API request header
<a name="signature-v4-troubleshooting-credential-header"></a>

When the authorization header is empty, the credential key or signature is missing or incorrect, the header doesn’t start with an algorithm name, or the key value pairs don’t include an equal sign, you receive one of the following errors:
+ Authorization header cannot be empty.
+ Authorization header requires 'Credential' parameter.
+ Authorization header requires 'Signature' parameter.
+ The signature contains an invalid key=value pair (missing equal-sign) in Authorization header.

Make sure that the SigV4 authorization header you added in [Calculate the signature](reference_sigv-create-signed-request.md#calculate-signature) includes the correct credential key, and also includes the request date using either HTTP Date or the `x-amz-date` header.

If you received an IncompleteSignatureException error and the construction of the signature is correct, you can verify that the authorization header was not modified in transit to the AWS service by computing a SHA-256 hash and B64 encoding of the authorization header in your client-side request.

1. Get the [authorization header](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-authentication-methods.html) you sent in the request. Your authorization header appears similar to the following example:

   ```
   Authorization: AWS4-HMAC-SHA256 
   Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, 
   SignedHeaders=host;range;x-amz-date,
   Signature=example-generated-signature
   ```

1. Compute a SHA-256 hash of the authorization header.

   ```
   hashSHA256(rawAuthorizationHeader) = hashedAuthorizationHeader
   ```

1. Encode the hashed authorization header to Base64 format. 

   ```
   base64(hashedAuthorizationHeader) = encodedHashedAuthorizationHeader
   ```

1. Compare the hashed and encoded string you just calculated against the string you received in your error message. Your error message should be similar to the following example:

   ```
   com.amazon.coral.service#IncompleteSignatureException: 
   The signature contains an in-valid key=value pair (missing equal-sign) 
   in Authorization header (hashed with SHA-256 and encoded with Base64): 
   '9c574f83b4b950926da4a99c2b43418b3db8d97d571b5e18dd0e4f3c3ed1ed2c'.
   ```
+ If the two hashes differ, then some part of the authorization header changed in transit. This change could be due to your network or client handlers attaching signed headers or changing the authorization header in some way. 
+ If the two hashes match, the authorization header you sent in the request matches what AWS received. Review the error message you received to determine if the issue is the result of incorrect credentials or signature. These errors are covered in the other sections on this page. 

## Credential scope errors
<a name="signature-v4-troubleshooting-credential-scope"></a>

The credential scope you created in [Create a string to sign](reference_sigv-create-signed-request.md#create-string-to-sign) restricts a signature to a specific date, Region, and service. This string has the following format:

```
YYYYMMDD/region/service/aws4_request
```

**Note**  
If you are using SigV4a, the Region is not included in credential scope.

**Date**  
If the credential scope does not specify the same date as the x-amz-date header, the signature verification step fails with the following error message:

```
Date in Credential scope does not match YYYYMMDD from ISO-8601 version of date from HTTP
```

If the request specifies a time in the future, the signature verification step fails with the following error message:

```
Signature not yet current: date is still later than date
```

If the request has expired, the signature verification step fails with the following error message:

```
Signature expired: date is now earlier than date
```

**Region**  
If the credential scope does not specify the same Region as the request, the signature verification step fails with the following error message:

```
Credential should be scoped to a valid Region, not region-code
```

**Service**  
If the credential scope does not specify the same service as the host header, the signature verification step fails with the following error message:

```
Credential should be scoped to correct service: 'service'
```

**Termination string**  
If the credential scope does not end with aws4\$1request, the signature verification step fails with the following error message:

```
Credential should be scoped with a valid terminator: 'aws4_request'
```

## Key signing errors
<a name="signature-v4-troubleshooting-key-signing"></a>

Errors that are caused by incorrect derivation of the signing key or improper use of cryptography are more difficult to troubleshoot. After you verify that the canonical string and the string to sign are correct, you can also check for one of the following issues:
+ The secret access key does not match the access key ID that you specified.
+ There is a problem with your key derivation code.

To verify that the secret key matches the access key ID, you can test them with a known working implementation. For example, use an AWS SDK or the AWS CLI to make a request to AWS. For examples, see [Request signature examples](reference_sigv-examples.md)