

# Crie uma solicitação assinada de API da AWS
<a name="reference_sigv-create-signed-request"></a>

**Importante**  
Caso use um SDK da AWS (consulte [Código de exemplo e bibliotecas](https://aws.amazon.com/developer/)) ou a ferramenta AWS Command Line Interface (AWS CLI) para enviar solicitações de API à AWS, você pode pular esta seção, pois os clientes do SDK e CLI autenticam as solicitações usando as chaves de acesso fornecidas por você. A menos que haja um bom motivo para não usar, é recomendável usar sempre um SDK ou a CLI.  
Em regiões compatíveis com várias versões de assinatura, assinar as solicitações manualmente significa que é necessário especificar qual versão de assinatura está sendo usada. Quando você fornece solicitações para pontos de acesso multirregionais, os SDKs e a CLI automaticamente alternam para o uso do Signature Version 4A, sem configuração adicional.

Você pode usar o protocolo de assinatura SigV4 da AWS para criar uma solicitação assinada para solicitações de API da AWS.

1. A criação de uma solicitação canônica com base nos detalhes da solicitação.

1. O cálculo uma assinatura usando suas credenciais da AWS.

1. Adicionar essa assinatura à solicitação como um cabeçalho de autorização.

A AWS, em seguida, replica esse processo e verifica a assinatura, concedendo ou negando o acesso adequadamente.

Para ver como você pode usar o AWS SigV4 para assinar solicitações de API, consulte [Exemplos de assinatura de solicitação](reference_sigv-examples.md).

A tabela a seguir descreve as funções usadas no processo de criação de uma solicitação assinada. É necessário implementar o código para essas funções. Para obter mais informações, consulte os [exemplos de código nos AWS SDKs](reference_sigv.md#reference_aws-signing-resources).


| Função | Descrição | 
| --- | --- | 
|  `Lowercase()`  |  Converta a string em letras minúsculas.  | 
|  `Hex()`  |  Codificação de base 16 em letras minúsculas.  | 
|  `SHA256Hash()`  |  Função de hash criptográfico do Secure Hash Algorithm (SHA).  | 
|  `HMAC-SHA256()`  |  Calcula o HMAC usando o algoritmo SHA256 com a chave de assinatura fornecida. Esta é a assinatura final quando você assina com o SigV4.  | 
|  `ECDSA-Sign`  |  Assinatura do Algoritmo de assinatura digital de curva elíptica (ECDSA) calculada usando assinaturas assimétricas baseadas em criptografia de chave pública-privada.   | 
|  `KDF(K, Label, Context, L)`  |  Um KDF NIST SP800-108 no Modo Contador usando a função PRF HMAC-SHA256, conforme definido no [NIST SP 800-108r1](https://doi.org/10.6028/NIST.SP.800-108r1-upd1).  | 
|  `Oct2Int(byte[ ])`  |  Uma função de octeto para inteiro, conforme descrito no ANSI X9.62.  | 
|  `Trim()`  |  Remova qualquer espaço em branco inicial e final.  | 
|  `UriEncode()`  |  O URI codifica cada byte. O UriEncode() deve aplicar as seguintes regras: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/pt_br/IAM/latest/UserGuide/reference_sigv-create-signed-request.html)  As funções UriEncode padrão fornecidas por sua plataforma de desenvolvimento podem não funcionar devido às diferenças na implementação e à ambiguidade relacionada nos RFCs subjacentes. É recomendável escrever sua própria função UriEncode personalizada para garantir que a codificação funcione.  Para ver um exemplo de uma função UriEncode em Java, consulte [Java Utilities](https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/util/SdkHttpUtils.java#L66) no site do GitHub.  | 

**nota**  
Ao assinar as solicitações, você pode usar o AWS SigV4 ou o AWS SigV4a. A principal diferença entre os dois está na forma como a assinatura é calculada. Com o SigV4a, o conjunto de regiões é incluído na string a ser assinada, mas não faz parte da etapa de derivação da credencial.

## Solicitação de assinatura com credenciais de segurança temporárias
<a name="temporary-security-credentials"></a>

Em vez de usar credenciais de longo prazo para assinar uma solicitação, é possível usar credenciais de segurança temporárias fornecidas pelo AWS Security Token Service (AWS STS).

Ao usar credenciais de segurança temporárias, é necessário adicionar o código `X-Amz-Security-Token` ao cabeçalho de autorização ou incluí-lo na string de consulta para manter o token da sessão. Alguns serviços exigem que você adicione `X-Amz-Security-Token` à solicitação canônica. Outros serviços exigem apenas que você adicione `X-Amz-Security-Token` no final, depois de calcular a assinatura. Verifique a documentação de cada AWS service (Serviço da AWS) para obter requisitos específicos.

## Resumo das etapas de assinatura
<a name="create-signed-request-steps"></a>

**Criar uma solicitação canônica**  
Organize o conteúdo da solicitação (host, ação, cabeçalhos etc.) em um formato padrão canônico. A solicitação canônica é um recurso usado para criar a string para assinar. Para obter detalhes sobre a criação da solicitação canônica, consulte [Elementos de uma assinatura de solicitação de API da AWS](reference_sigv-signing-elements.md).

**Criar um hash para a solicitação canônica**  
Faça o hash da solicitação canônica usando o mesmo algoritmo que você usou para criar o hash da carga útil. O hash da solicitação canônica é uma string de caracteres hexadecimais em minúsculas.

**Criar uma string para assinar**  
Crie uma string para assinar com a solicitação canônica e informações adicionais, como o algoritmo, data de solicitação, escopo de credencial e o hash da solicitação canônica.

**Derivar uma chave de assinatura**  
Use a chave de acesso secreta para derivar a chave usada para assinar a solicitação.

**Calcular a assinatura**  
Realize uma operação de hash com chave na string para assinar usando a chave de assinatura derivada como a chave de hash.

**Adicionar a assinatura à solicitação**  
Adicione a assinatura calculada a um cabeçalho de HTTP ou à string de consulta da solicitação.

## Criar uma solicitação canônica
<a name="create-canonical-request"></a>

Para criar uma solicitação canônica, concatene as strings a seguir separadas por caracteres de linha nova. Isso ajuda a garantir que a assinatura que você calcula possa corresponder à assinatura que a AWS calcula.

```
<HTTPMethod>\n
<CanonicalURI>\n
<CanonicalQueryString>\n
<CanonicalHeaders>\n
<SignedHeaders>\n
<HashedPayload>
```
+ *HTTPMethod*: o método HTTP, como `GET`, `PUT`, `HEAD` e `DELETE`.
+ *CanonicalUri*: a versão codificada em URI do componente de caminho absoluto do URI, começando com o código `/` que segue o nome do domínio e indo até o final da string ou até o caractere de ponto de interrogação (`?`) se você tiver parâmetros de string de consulta. Se o caminho absoluto estiver vazio, use um caractere de barra inclinada (`/`). O URI no exemplo a seguir, `/amzn-s3-demo-bucket/myphoto.jpg`, é o caminho absoluto, e você não codifica o `/` no caminho absoluto:

  ```
  http://s3.amazonaws.com/amzn-s3-demo-bucket/myphoto.jpg
  ```
+ *CanonicalQueryString*: os parâmetros da string de consulta codificados por URI. Codifique por URI cada nome e valor individualmente. Também é necessário classificar os parâmetros na string de consulta canônica em ordem alfabética pelo nome da chave. A classificação ocorre após a codificação. A string de consulta no seguinte exemplo de URI é:

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

  A string de consulta canônica é como este exemplo (quebras de linha foram adicionadas ao exemplo para facilitar a leitura):

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

  Quando uma solicitação se destina a um sub-recurso, o valor do parâmetro de consulta correspondente é uma string vazia (`""`). Por exemplo, o URI a seguir identifica o sub-recurso `ACL` no bucket `amzn-s3-demo-bucket`:

   

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

  Nesse caso, a CanonicalQueryString seria:

   

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

  Caso o URI não contenha um `?`, não há strings de consulta na solicitação, e você define a string de consulta canônica como uma string vazia (`""`). Você ainda precisará incluir o caractere de linha nova (`"\n"`).
+ *CanonicalHeaders*: uma lista de cabeçalhos de solicitação com os respectivos valores. Os pares individuais de nome e valor do cabeçalho são separados pelo caractere de linha nova (`"\n"`). Veja a seguir um exemplo de um CanonicalHeader:

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

  A lista CanonicalHeaders deve conter:
  + Cabeçalho HTTP `host`
  + Se o cabeçalho `Content-Type` estiver presente na solicitação, você deverá adicioná-lo à lista *CanonicalHeaders*. 
  + Também deverão ser adicionados todos os cabeçalhos `x-amz-*` que você pretende incluir na solicitação. Por exemplo, se você estiver usando credenciais de segurança temporárias, precisará incluir o `x-amz-security-token` na solicitação. É necessário adicionar esse cabeçalho à lista de *CanonicalHeaders*.
  + Para SigV4a, você deve incluir um cabeçalho de conjunto de regiões que especifique o conjunto de regiões em que a solicitação será válida. O cabeçalho `X-Amz-Region-Set` é especificado como uma lista de valores separados por vírgula. O exemplo a seguir mostra um cabeçalho de região que permite fazer uma solicitação nas regiões us-east-1 e us-west-1.

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

    Você pode usar curingas (\$1) em regiões para especificar várias regiões. No exemplo a seguir, o cabeçalho permite que uma solicitação seja feita tanto na região us-west-1 quanto na us-west-2.

    `X-Amz-Region-Set=us-west-*`
**nota**  
O cabeçalho `x-amz-content-sha256` é obrigatório para solicitações da AWS do Amazon S3. Ele fornece um hash da carga da solicitação. Se não houver carga útil, será necessário fornecer o hash de uma string vazia.

  Todo nome de cabeçalho deve:
  + usar caracteres minúsculos.
  + ser exibido em ordem alfabética.
  + ser seguido por dois pontos (`:`).

  Para valores, é necessário:
  + remover todos os espaços à esquerda ou à direita.
  + converter espaços sequenciais em um espaço único.
  + separar os valores de um cabeçalho de múltiplos valores usando vírgulas.
  + É necessário incluir na assinatura o cabeçalho host (HTTP/1.1) ou o cabeçalho :authority (HTTP/2) e quaisquer cabeçalhos `x-amz-*`. Opcionalmente, você pode incluir outros cabeçalhos padrão na assinatura, como content-type.

  As funções `Lowercase()` e `Trim()` usadas neste exemplo estão descritas na seção anterior.

  Veja a seguir um exemplo de string `CanonicalHeaders`. O nomes dos cabeçalhos estão em letras minúsculas e são classificados.

   

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

   
**nota**  
Para fins de cálculo de uma assinatura de autorização, somente o host e cabeçalhos `x-amz-*` são obrigatórios; no entanto, para evitar a adulteração de dados, considere incluir os cabeçalhos adicionais no cálculo da assinatura.  
Não inclua cabeçalhos hop-by-hop que são alterados com frequência durante o trânsito em um sistema complexo. Isso inclui todos os cabeçalhos de transporte voláteis que são alterados por proxies, balanceadores de carga e nós em um sistema distribuído, incluindo `connection`, `x-amzn-trace-id`, `user-agent`, `keep-alive`, `transfer-encoding`, `TE`, `trailer`, `upgrade`, `proxy-authorization` e `proxy-authenticate`.
+ *SignedHeaders*: uma lista ordenada alfabeticamente, separada por ponto e vírgula, de nomes de cabeçalhos de solicitação em letras minúsculas. Os cabeçalhos de solicitação da lista são os mesmos cabeçalhos que você incluiu na string `CanonicalHeaders`. Para o exemplo anterior, o valor de *SignedHeaders* seria:

  ```
  host;x-amz-content-sha256;x-amz-date
  ```
+ *HashedPayload*: uma string criada usando a carga útil no corpo da solicitação HTTP como entrada para uma função de hash. Esta string usa caracteres hexadecimais minúsculos.

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

  Se não houver carga útil na solicitação, calcule um hash da string vazia. Por exemplo, ao recuperar um objeto usando uma solicitação `GET`, não haverá nada na carga útil.

  ```
  Hex(SHA256Hash(""))
  ```
**nota**  
Para o Amazon S3, inclua a string literal `UNSIGNED-PAYLOAD` ao construir uma solicitação canônica e defina o mesmo valor como o cabeçalho `x-amz-content-sha256` ao enviar a solicitação.  
`Hex(SHA256Hash("UNSIGNED-PAYLOAD"))`

## Criar um hash para a solicitação canônica
<a name="create-canonical-request-hash"></a>

Crie um hash (resumo) da solicitação canônica usando o mesmo algoritmo que você usou para criar o hash da carga útil. O hash da solicitação canônica é uma string de caracteres hexadecimais em minúsculas.

## Criar uma string para assinar
<a name="create-string-to-sign"></a>

Para criar uma string para assinar, concatene as strings a seguir separadas por caracteres de linha nova. Não termine esta string com um caractere de linha nova.

```
Algorithm \n
RequestDateTime \n
CredentialScope  \n
HashedCanonicalRequest
```
+ *Algorithm*: o algoritmo usado para criar o hash da solicitação canônica.
  + SigV4: use `AWS4-HMAC-SHA256` para especificar o algoritmo de hash `HMAC-SHA256`. 
  + SigV4a: use `AWS4-ECDSA-P256-SHA256` para especificar o algoritmo de hash `ECDSA-P256-SHA-256`. 
+ *RequestDateTime*: a data e a hora usadas no escopo da credencial. Esse valor é a hora UTC atual no formato ISO 8601 (por exemplo, `20130524T000000Z`).
+ *CredentialScope*: o escopo de credencial, que restringe a assinatura resultante à região e ao serviço especificados.
  + SigV4: as credenciais incluem o ID da chave de acesso, a data no formato `YYYYMMDD`, o código da região, o código do serviço e a string `aws4_request` de término separados por barras (/). O código da região, o código do serviço e a string de término devem usar caracteres minúsculos. A string tem o seguinte formato: `YYYYMMDD/region/service/aws4_request`.
  + SigV4a: as credenciais incluem a data no formato `YYYYMMDD`, o nome do serviço e a string `aws4_request` de término separados por barras (/). Observe que o escopo da credencial não inclui a região, pois ela é englobada em um cabeçalho `X-Amz-Region-Set` separado. A string tem o seguinte formato: `YYYYMMDD/service/aws4_request`.
+ *HashedCanonicalRequest*: o hash da solicitação canônica, calculada na etapa anterior.

Veja a seguir um exemplo de string para assinar.

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

## Derivar uma chave de assinatura
<a name="derive-signing-key"></a>

Para derivar uma chave de assinatura, escolha um dos processos a seguir para calcular uma chave de assinatura para SigV4 ou SigV4a.

### Derivar uma chave de assinatura para SigV4
<a name="derive-signing-key-sigv4"></a>

Para derivar uma chave de assinatura para SigV4, realize uma sequência de operações de hash com chave (HMAC) no serviço, região e data da solicitação usando sua chave de acesso secreta da AWS como a chave para a operação inicial de hashing.

Para cada etapa, chame a função de hash com a chave e os dados necessários. O resultado de cada chamada para a função de hash torna-se a entrada para a próxima chamada para a função de hash.

O exemplo a seguir mostra como você deriva a `SigningKey` usada na próxima seção desse procedimento, mostrando a ordem na qual sua entrada é concatenada e transformada em hash. O código `HMAC-SHA256` é a função de hash usada para fazer o hash dos dados, conforme mostrado.

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

**Entrada obrigatória**
+ `Key`: uma string que contém sua chave de acesso secreta.
+ `Date`: uma string que contém a data usada no escopo da credencial, no formato *AAAAMMDD*.
+ `Region`: uma string que contém o código da região (por exemplo, `us-east-1`).

  Para obter uma lista de regiões de strings, consulte [Regional endpoints](https://docs.aws.amazon.com//general/latest/gr/rande.html#regional-endpoints), na *Referência geral da AWS*.
+ `Service`: uma string que contém o código do serviço (por exemplo, `ec2`).
+ A string para assinar que você criou na etapa anterior.

**Derivar uma chave de assinatura para SigV4**

1. Concatene `"AWS4"` e a chave de acesso secreta. Chame a função de hash com a string concatenada como chave e a string de data como os dados.

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

1. Chame a função de hash com o resultado da chamada anterior como chave e a string de região como os dados.

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

1. Chame a função de hash com o resultado da chamada anterior como a chave e a string de serviço como os dados.

   O código do serviço é definido pelo serviço. Você pode usar [get-products](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/pricing/get-products.html) na *AWS Pricing CLI* para retornar o código de serviço de um serviço.

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

1. Chame a função de hash com o resultado da chamada anterior como a chave e “aws4\$1request” como os dados.

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

### Derivar uma chave de assinatura para SigV4a
<a name="derive-signing-key-sigv4a"></a>

Para criar uma chave de assinatura para SigV4a, use o processo a seguir para derivar um par de chaves da chave de acesso secreta. Para obter um exemplo de implementação dessa derivação, consulte a [implementação da biblioteca C99 da autenticação do lado do cliente da AWS](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
}
```

## Calcular a assinatura
<a name="calculate-signature"></a>

Depois de derivar a chave de assinatura, calcule a assinatura para adicionar à sua solicitação. Esse procedimento varia de acordo com a versão de assinatura que você usa.

**Para calcular uma assinatura para SigV4**

1. Chame a função de hash com o resultado da chamada anterior como a chave e a **string para assinar** como os dados. Use a chave de assinatura derivada como a chave de hash para esta operação. O resultado é a assinatura como valor binário.

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

1. Converta a assinatura da representação binária em hexadecimal, em caracteres minúsculos.

**Para calcular uma assinatura para SigV4a**

1. Usando o algoritmo de assinatura digital (ECDSA P-256), assine a **string para assinar** que você criou na etapa anterior. A chave usada para essa assinatura é a chave assimétrica privada derivada da chave de acesso secreta, conforme descrito acima.

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

1. Converta a assinatura da representação binária em hexadecimal, em caracteres minúsculos.

## Adicionar a assinatura à solicitação
<a name="add-signature-to-request"></a>

Adicione a assinatura calculada à sua solicitação.

**Example Exemplo: cabeçalho de autorização**  
**SigV4**  
O exemplo a seguir mostra um cabeçalho `Authorization` para a ação `DescribeInstances` usando o AWS SigV4. Para facilitar a leitura, este exemplo está formatado com quebras de linha. Em seu código, deve ser uma string contínua. Não há vírgula entre o algoritmo e `Credential`. Porém, os outros elementos devem ser separados por vírgulas.

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

**Sigv4a**  
O exemplo a seguir mostra um cabeçalho Authorization para a ação `CreateBucket` usando o AWS SigV4a. Para facilitar a leitura, este exemplo está formatado com quebras de linha. Em seu código, deve ser uma string contínua. Não há vírgula entre o algoritmo e a credencial. Porém, os outros elementos devem ser separados por vírgulas.

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

**Example Exemplo: solicitação com parâmetros de autenticação na string de consulta**  
**SigV4**  
O exemplo a seguir mostra uma consulta para a ação `DescribeInstances` usando o AWS SigV4 que contém as informações de autenticação. Para facilitar a leitura, esse exemplo está formatado com quebras de linha e não codificado de URL. Em seu código, a string de consulta deve ser uma string contínua codificada de URL.

```
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**  
O exemplo a seguir mostra uma consulta para a ação `CreateBucket` usando o AWS SigV4a que contém as informações de autenticação. Para facilitar a leitura, esse exemplo está formatado com quebras de linha e não codificado de URL. Em seu código, a string de consulta deve ser uma string contínua codificada de URL.

```
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
```