

# Creación de una solicitud de API de AWS firmada
<a name="reference_sigv-create-signed-request"></a>

**importante**  
Si utiliza un SDK de AWS (consulte [Sample Code and Libraries](https://aws.amazon.com/developer/)) o la herramienta de AWS Command Line Interface (AWS CLI) para enviar solicitudes de API a AWS, puede omitir esta sección porque los clientes del SDK y la CLI autentican sus solicitudes mediante las claves de acceso que les proporciona. A menos que tenga una razón específica para no hacerlo, le recomendamos que utilice siempre un SDK o la CLI.  
En las regiones en las que se admiten varias versiones de firma, las solicitudes de firma manual significan que debe especificar qué versión de firma se utiliza. Cuando envía solicitudes a puntos de acceso de varias regiones, los SDK y la CLI cambian de forma automática a Signature Version 4A sin configuración adicional.

Puede utilizar el protocolo de firma de AWS SigV4 a fin de crear una solicitud firmada para las solicitudes de API de AWS.

1. Crear una solicitud canónica en función de los detalles de la solicitud.

1. Calcular una firma con sus credenciales de AWS.

1. Agregar esta firma a la solicitud como encabezado de autorización.

Luego, AWS replica este proceso y verifica la firma, concediendo o denegando el acceso en consecuencia.

Para conocer cómo puede utilizar AWS SigV4 para firmar solicitudes de API, consulte [Ejemplos de firmas de solicitudes](reference_sigv-examples.md).

En la siguiente tabla, se describen las funciones que se usan en el proceso de creación de una solicitud firmada. Debe implementar código para estas funciones. Para obtener más información, consulte [ejemplos de código en los SDK de AWS](reference_sigv.md#reference_aws-signing-resources).


| Función | Descripción | 
| --- | --- | 
|  `Lowercase()`  |  Convierta la cadena de caracteres en minúsculas.  | 
|  `Hex()`  |  Codificación en minúsculas en base 16.  | 
|  `SHA256Hash()`  |  Función de hash criptográfico del algoritmo de hash seguro (SHA).  | 
|  `HMAC-SHA256()`  |  Calcula el HMAC mediante el algoritmo SHA256 con la clave de firma proporcionada. Esta es la firma final cuando firma con SigV4.  | 
|  `ECDSA-Sign`  |  La firma del Algoritmo de firma digital de curva elíptica (ECDSA) se calcula mediante firmas asimétricas basadas en la criptografía de clave público-privada.   | 
|  `KDF(K, Label, Context, L)`  |  Una KDF de NIST SP800-108 en modo de contador que utiliza la función PRF HMAC-SHA256, tal como se define en [NIST SP 800-108r1](https://doi.org/10.6028/NIST.SP.800-108r1-upd1).  | 
|  `Oct2Int(byte[ ])`  |  Una función de octeto a entero, tal como se describe en ANSI X9.62.  | 
|  `Trim()`  |  Elimine cualquier espacio en blanco inicial o final.  | 
|  `UriEncode()`  |  El URI codifica cada byte. UriEncode() debe aplicar las siguientes reglas: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/es_es/IAM/latest/UserGuide/reference_sigv-create-signed-request.html)  Es posible que las funciones estándar de UriEncode que proporciona su plataforma de desarrollo no funcionen debido a las diferencias en la implementación y a la ambigüedad relacionada en las RFC subyacentes. Le recomendamos que escriba su propia función UriEncode personalizada para asegurarse de que la codificación funcione.  Para ver un ejemplo de una función UriEncode en Java, consulte [Utilidades de Java](https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/util/SdkHttpUtils.java#L66) en el sitio web de GitHub.  | 

**nota**  
Al firmar sus solicitudes, puede utilizar cualquiera de las siguientes opciones: AWS SigV4 o AWS SigV4a. La diferencia clave entre las dos se determina por la forma en que se calcula la firma. Con SigV4a, el conjunto de regiones se incluye en la cadena que se va a firmar, pero no forma parte del paso de derivación de credenciales.

## Solicitudes de firma con credenciales de seguridad temporales
<a name="temporary-security-credentials"></a>

En lugar de utilizar credenciales de larga duración para firmar una solicitud, puede utilizar las credenciales de seguridad temporales proporcionadas por AWS Security Token Service (AWS STS).

Cuando utilice credenciales de seguridad temporales, debe agregar `X-Amz-Security-Token` al encabezado de autorización o incluirlo a la cadena de consulta para contener el token de sesión. Algunos servicios requieren que agregue `X-Amz-Security-Token` a la solicitud canónica. Otros servicios requieren que solo agregue `X-Amz-Security-Token` al final, después de calcular la firma. Consulte la documentación de cada Servicio de AWS para conocer los requisitos específicos.

## Resumen de pasos de firma
<a name="create-signed-request-steps"></a>

**Crear una solicitud canónica**  
Organice el contenido de la solicitud (host, acción, encabezados, etc.) en un formato canónico estándar. La solicitud canónica es uno de los datos de entrada utilizados con el fin de crear la cadena para firmar. Para obtener detalles sobre cómo crear la solicitud canónica, consulte [Elementos de una firma de solicitud a la API de AWS](reference_sigv-signing-elements.md).

**Crear un hash de la solicitud canónica**  
Cree un hash de la solicitud canónica con el mismo algoritmo que utilizó para crear el hash de la carga. El hash de la solicitud canónica es una cadena de caracteres hexadecimales en minúsculas.

**Crear una cadena para firmar**  
Cree una cadena para firmar con la solicitud canónica e información adicional, como el algoritmo, la fecha de la solicitud, el ámbito de la credencial y el hash de la solicitud canónica.

**Generar una clave de firma**  
Utilice la clave de acceso secreta para obtener la clave utilizada para firmar la solicitud.

**Calcular la firma**  
Lleve a cabo una operación hash con clave en la cadena para firmar con la clave de firma generada como clave de hash.

**Agregar la firma a la solicitud**  
Agregue la firma calculada a un encabezado HTTP o a la cadena de consulta de la solicitud.

## Crear una solicitud canónica
<a name="create-canonical-request"></a>

Para crear una solicitud canónica, concatene las siguientes cadenas, separadas por caracteres de nueva línea. Esto ayuda a garantizar que la firma que calcula pueda coincidir con la firma que calcula AWS.

```
<HTTPMethod>\n
<CanonicalURI>\n
<CanonicalQueryString>\n
<CanonicalHeaders>\n
<SignedHeaders>\n
<HashedPayload>
```
+ *HTTPMethod*: el método HTTP, como `GET`, `PUT`, `HEAD` y `DELETE`.
+ *CanonicalUri*: la versión codificada en URI del componente de ruta absoluta, que comienza con la `/` que sigue al nombre de dominio y continúa hasta el final de la cadena o del signo de interrogación (`?`) si tiene parámetros de cadena de consulta. Si la ruta absoluta está vacía, utilice un carácter de barra diagonal (`/`). El URI del siguiente ejemplo, `/amzn-s3-demo-bucket/myphoto.jpg`, es la ruta absoluta y no se codifica la `/` en la ruta absoluta:

  ```
  http://s3.amazonaws.com/amzn-s3-demo-bucket/myphoto.jpg
  ```
+ *CanonicalQueryString*: los parámetros de la cadena de consulta codificados en URI. Codifique en URI cada nombre y valor de forma individual. También debe ordenar los parámetros de la cadena de consulta canónica alfabéticamente por nombre de clave. La clasificación se produce después de la codificación. La cadena de consulta del siguiente ejemplo de URI es:

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

  La cadena de consulta canónica es la siguiente (se agregan saltos de línea a este ejemplo para facilitar la lectura):

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

  Cuando una solicitud se dirige a un subrecurso, el valor del parámetro de consulta correspondiente será una cadena vacía (`""`). Por ejemplo, el siguiente URI identifica el subrecurso `ACL` en el bucket `amzn-s3-demo-bucket`:

   

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

  En este caso, la cadena CanonicalQueryString sería:

   

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

  Si el URI no incluye un `?`, no hay ninguna cadena de consulta en la solicitud y establece la cadena de consulta canónica en una cadena vacía (`""`). Aún tendrá que incluir el carácter de nueva línea (`"\n"`).
+ *CanonicalHeaders*: una lista de los encabezados de las solicitudes con sus valores. Los pares individuales de nombre y valor del encabezado se encuentran separados por el carácter de nueva línea (`"\n"`). El siguiente es un ejemplo de un CanonicalHeader:

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

  La lista CanonicalHeaders debe incluir lo siguiente:
  + Encabezado de `host` HTTP.
  + Si el encabezado `Content-Type` se encuentra en la solicitud, debe agregarlo a la lista *CanonicalHeaders*. 
  + También debe agregar cualquier encabezado `x-amz-*` que planea incluir en su solicitud. Por ejemplo, si utiliza credenciales de seguridad temporales, debe incluir `x-amz-security-token` en su solicitud. Debe agregar este encabezado a la lista de *CanonicalHeaders*.
  + En el caso de SigV4a, debe incluir un encabezado de conjunto de regiones que especifique el conjunto de regiones en las que será válida la solicitud. El encabezado `X-Amz-Region-Set` se especifica como una lista de valores separados por comas. En el siguiente ejemplo, se muestra un encabezado de región que permite realizar una solicitud tanto en las regiones us-east-1 como us-west-1.

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

    Puede utilizar comodines (\$1) en las regiones para especificar varias regiones. En el siguiente ejemplo, el encabezado permite realizar una solicitud tanto en us-west-1 como en us-west-2.

    `X-Amz-Region-Set=us-west-*`
**nota**  
El encabezado `x-amz-content-sha256` es obligatorio para las solicitudes de AWS de Amazon S3. Proporciona un hash de la carga de solicitud. Si no hay ninguna carga, debe proporcionar el hash de una cadena vacía.

  Cada nombre de encabezado debe:
  + tener caracteres en minúsculas;
  + aparecer en orden alfabético;
  + ir seguido de dos puntos (`:`).

  En el caso de los valores, debe:
  + recortar los espacios iniciales o finales;
  + convertir espacios secuenciales en un solo espacio;
  + separar los valores de un encabezado con varios valores mediante comas.
  + Debe incluir el encabezado de host (HTTP/1.1) o el encabezado :authority (HTTP/2) y cualquier encabezado `x-amz-*` de la firma. Si lo desea, puede incluir otros encabezados estándar en la firma, como content-type.

  Las funciones `Lowercase()` y `Trim()` que se utilizan en este ejemplo se describen en la sección anterior.

  La siguiente es una cadena de `CanonicalHeaders` de ejemplo. Los nombres de encabezado se encuentran en minúsculas y ordenados.

   

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

   
**nota**  
Para calcular una firma de autorización, solo se requieren el host y cualquier encabezado `x-amz-*`; sin embargo, a fin de evitar la manipulación de datos, debería considerar la posibilidad de incluir encabezados adicionales en el cálculo de la firma.  
No incluya encabezados salto a salto que se modifican frecuentemente durante el tránsito por un sistema complejo. Esto incluye todos los encabezados de transporte volátiles que mutados por proxies, equilibradores de carga y los nodos de un sistema distribuido, como `connection`, `x-amzn-trace-id`, `user-agent`, `keep-alive`, `transfer-encoding`, `TE`, `trailer`, `upgrade`, `proxy-authorization` y `proxy-authenticate`.
+ *SignedHeaders*: una lista ordenada alfabéticamente y separada por punto y coma de nombres de encabezados de solicitudes en minúsculas. Los encabezados de las solicitudes de la lista son los mismos que incluyó en la cadena de `CanonicalHeaders`. En el caso anterior, el valor de *SignedHeaders* sería el siguiente:

  ```
  host;x-amz-content-sha256;x-amz-date
  ```
+ *HashedPayload*: una cadena creada con la carga del cuerpo de la solicitud HTTP como entrada para una función de hash. Esta cadena utiliza caracteres hexadecimales en minúscula.

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

  Si no hay ninguna carga en la solicitud, se calcula un hash de la cadena vacía, por ejemplo, cuando se recupera un objeto mediante una solicitud `GET`, no hay nada en la carga.

  ```
  Hex(SHA256Hash(""))
  ```
**nota**  
En el caso de Amazon S3, incluya la cadena literal `UNSIGNED-PAYLOAD` al crear una solicitud canónica y establezca el mismo valor que el valor del encabezado `x-amz-content-sha256` al enviar la solicitud.  
`Hex(SHA256Hash("UNSIGNED-PAYLOAD"))`

## Crear un hash de la solicitud canónica
<a name="create-canonical-request-hash"></a>

Cree un hash (resumen) de la solicitud canónica con el mismo algoritmo que utilizó para crear el hash de la carga. El hash de la solicitud canónica es una cadena de caracteres hexadecimales en minúsculas.

## Crear una cadena para firmar
<a name="create-string-to-sign"></a>

A fin de crear una cadena para firmar, concatene las siguientes cadenas, separadas por caracteres de nueva línea. No termine esta cadena con un carácter de nueva línea.

```
Algorithm \n
RequestDateTime \n
CredentialScope  \n
HashedCanonicalRequest
```
+ *Algorithm*: el algoritmo utilizado para crear el hash de la solicitud canónica.
  + SigV4: use `AWS4-HMAC-SHA256` para especificar el algoritmo hash `HMAC-SHA256`. 
  + SigV4a: use `AWS4-ECDSA-P256-SHA256` para especificar el algoritmo hash `ECDSA-P256-SHA-256`. 
+ *RequestDateTime*: la fecha y la hora utilizadas en el alcance de la credencial. Este valor es la hora UTC actual en formato ISO 8601 (por ejemplo, `20130524T000000Z`).
+ *CredentialScope*: el ámbito de la credencial, que restringe la firma resultante a la región y el servicio especificados.
  + SigV4: las credenciales incluyen su clave de acceso, la fecha en formato `YYYYMMDD`, el código de región, el código de servicio y la cadena de terminación `aws4_request`, separados por barras diagonales (/). El código de región, el código de servicio y la cadena de terminación deben utilizar caracteres en minúscula. La cadena tiene el siguiente formato: `YYYYMMDD/region/service/aws4_request`.
  + SigV4a: las credenciales incluyen la fecha con el formato `YYYYMMDD`, el nombre del servicio y la cadena de terminación `aws4_request`, separados por barras diagonales (/). Tenga en cuenta que el ámbito de las credenciales no incluye la región, ya que la región está cubierta en un encabezado `X-Amz-Region-Set` independiente. La cadena tiene el siguiente formato: `YYYYMMDD/service/aws4_request`.
+ *HashedCanonicalRequest*: el hash de la solicitud canónica, calculado en el paso anterior.

La siguiente es una cadena de ejemplo para firmar.

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

## Generar una clave de firma
<a name="derive-signing-key"></a>

Para obtener una clave de firma, elija uno de los siguientes procesos para calcular una clave de firma para SigV4 o SigV4a.

### Generar una clave de firma para SigV4
<a name="derive-signing-key-sigv4"></a>

Para generar una clave de firma para SigV4, lleve a cabo una sucesión de operaciones hash con clave (HMAC) en la fecha de la solicitud, la región y el servicio, con su clave de acceso secreta de AWS como clave de la operación hash inicial.

Para cada paso, llame a la función de hash con la clave y los datos necesarios. El resultado de cada llamada a la función de hash se convierte en la entrada de la siguiente llamada a la función de hash.

En el siguiente ejemplo, se muestra cómo se genera la `SigningKey` que se utiliza en la siguiente sección de este procedimiento y se muestra el orden en el que se concatena y se codifica la entrada. `HMAC-SHA256` es la función hash que se utiliza para codificar los datos, tal como se muestra.

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

**Datos de ingreso obligatorios**
+ `Key`: una cadena que contiene su clave de acceso secreta.
+ `Date`: una cadena que contiene la fecha utilizada en el alcance de la credencial con el formato *DDMMAAAA*.
+ `Region`: una cadena que contiene el código de región (por ejemplo, `us-east-1`).

  Para obtener una lista de cadenas de región, consulte [Regional Endpoints](https://docs.aws.amazon.com//general/latest/gr/rande.html#regional-endpoints) en la *Referencia general de AWS*.
+ `Service`: una cadena que contiene el código de servicio (por ejemplo, `ec2`).
+ La cadena para firmar que creó en el paso anterior.

**Para generar una clave de firma para SigV4**

1. Concatene `"AWS4"` y la clave de acceso secreta. Llame a la función de hash con la cadena concatenada como clave y la cadena de fecha como datos.

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

1. Llame a la función de hash con el resultado de la llamada anterior como clave y la cadena de región como datos.

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

1. Llame a la función de hash con el resultado de la llamada anterior como clave y la cadena de servicio como datos.

   El servicio define el código de servicio. Puede utilizar [get-products](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/pricing/get-products.html) en la *CLI de precios de AWS* para devolver el código de servicio de un servicio.

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

1. Llame a la función de hash con el resultado de la llamada anterior como clave y “aws4\$1request” como datos.

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

### Generar una clave de firma para SigV4a
<a name="derive-signing-key-sigv4a"></a>

Para crear una clave de firma para SiGV4a, utilice el siguiente proceso a fin de generar un par de claves a partir de la clave de acceso secreta. Para ver un ejemplo de una implementación de esta derivación, consulte la [implementación de la biblioteca C99 de la autenticación de AWS del lado del cliente](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 la firma
<a name="calculate-signature"></a>

Una vez que se genera la clave de firma, calcule la firma para agregar a la solicitud. Este procedimiento varía en función de la versión de firma que utilice.

**Para calcular una firma para SigV4**

1. Llame a la función de hash con el resultado de la llamada anterior como clave y la **cadena para firmar** como datos. Utilice la clave de firma generada como clave hash para esta operación. El resultado es la firma como valor binario.

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

1. Convierta la firma de representación binaria a hexadecimal, en caracteres en minúsculas.

**Para calcular una firma para SigV4a**

1. Con el algoritmo de firma digital (ECDSA P-256), firme la **cadena para firmar** que creó en el paso anterior. La clave utilizada para esta firma es la clave asimétrica privada derivada de la clave de acceso secreta descrita anteriormente.

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

1. Convierta la firma de representación binaria a hexadecimal, en caracteres en minúsculas.

## Agregar la firma a la solicitud
<a name="add-signature-to-request"></a>

Agregue la firma calculada a su solicitud.

**Example Ejemplo: encabezado de autorización**  
**SigV4**  
En el ejemplo siguiente se muestra un encabezado de `Authorization` para la acción `DescribeInstances`mediante AWS SigV4. Para facilitar la lectura, este ejemplo está formateado con saltos de línea. En su código, debe ser una cadena continua. No hay ninguna coma entre el algoritmo y `Credential`. Sin embargo, los demás elementos deben ir separados por comas.

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

**SigV4a**  
En el ejemplo siguiente se muestra un encabezado de autorización para la acción `CreateBucket` mediante AWS SigV4a. Para facilitar la lectura, este ejemplo está formateado con saltos de línea. En su código, debe ser una cadena continua. No hay ninguna coma entre el algoritmo y la credencial. Sin embargo, los demás elementos deben ir separados por comas.

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

**Example Ejemplo: solicitud con parámetros de autenticación en la cadena de consulta**  
**SigV4**  
En el siguiente ejemplo, se muestra una consulta para la acción `DescribeInstances` mediante AWS SigV4 que incluye la información de autenticación. Para facilitar la lectura, este ejemplo está formateado con saltos de línea y no está codificado en URL. En el código, la cadena de consulta debe ser una cadena continua codificada en 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**  
En el siguiente ejemplo, se muestra una consulta para la acción `CreateBucket` mediante AWS SigV4a que incluye la información de autenticación. Para facilitar la lectura, este ejemplo está formateado con saltos de línea y no está codificado en URL. En el código, la cadena de consulta debe ser una cadena continua codificada en 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
```