

# API 요청용 AWS Signature Version 4
<a name="reference_sigv"></a>

**중요**  
AWS SDK([샘플 코드 및 라이브러리](https://aws.amazon.com/developer/) 참조) 또는 AWS Command Line Interface(AWS CLI) 도구를 사용하여 API 요청을 AWS로 전송하는 경우 SDK 및 CLI 클라이언트는 사용자 요청 인증에 사용자가 제공한 액세스 키를 사용하므로 서명 프로세스를 건너뛸 수 있습니다. 그럴 만한 이유가 없는 경우 항상 SDK 또는 CLI를 사용하는 것이 좋습니다.  
여러 서명 버전을 지원하는 리전에서는 수동 서명을 요청하는 경우 사용할 서명 버전을 지정해야 합니다. 다중 리전 액세스 포인트로 요청을 공급하는 경우 SDK와 CLI가 자동으로 추가 구성 없이 서명 버전 4A를 사용하는 것으로 전환됩니다.

요청에서 보내는 인증 정보에는 서명이 포함되어야 합니다. AWS Signature Version 4(SigV4)는 AWS API 요청에 인증 정보를 추가하기 위한 AWS 서명 프로토콜입니다.

비밀 액세스 키를 사용하여 API 요청에 서명하지 않습니다. 대신 SigV4 서명 프로세스를 사용합니다. 서명 요청:

1. 요청 세부 정보를 기반으로 표준 요청 생성.

1. AWS 자격 증명을 사용하여 서명 계산.

1. 이 서명을 요청에 Authorization 헤더로 추가.

AWS에서는 이 프로세스를 복제하고 서명을 확인하여 그에 따라 액세스를 허용하거나 거부합니다.

대칭 SigV4를 사용하려면 특정 날짜에 단일 AWS 리전의 단일 AWS 서비스로 범위가 지정된 키를 생성해야 합니다. 따라서 각 리전마다 키와 계산된 서명이 달라지므로 서명의 대상 리전을 알아야 합니다.

비대칭 서명 버전 4(SigV4a)는 새로운 알고리즘을 사용한 서명을 지원하고 두 개 이상의 AWS 리전에서 확인 가능한 개별 서명을 생성하는 것을 지원하는 확장 프로그램입니다. SigV4a를 사용하면 리전 간에 원활한 라우팅 및 장애 조치를 통해 여러 리전에 대한 요청에 서명할 수 있습니다. AWS SDK 또는 AWS CLI를 사용하여 다중 리전 서명이 필요한 기능을 간접적으로 호출하면 서명 유형이 SigV4a를 사용하도록 자동으로 변경됩니다. 세부 정보는 [AWS SigV4a 작동 방식](#how-sigv4a-works)을 참조하세요.

## AWS SigV4 작동 방식
<a name="how-aws-signing-works"></a>

다음 단계에서는 SigV4에서 서명을 계산하는 일반적인 프로세스에 대해 설명합니다.

1. **서명할 문자열**은 요청 유형에 따라 다릅니다. 예를 들어 HTTP Authorization 헤더 또는 쿼리 파라미터를 인증에 사용하는 경우 요청 요소 조합을 사용하여 서명할 문자열을 생성합니다. HTTP POST 요청의 경우 요청의 `POST` 정책은 서명하는 문자열입니다.

1. **서명 키**는 각 단계의 결과를 다음 단계에 제공하는 일련의 계산입니다. 마지막 단계는 서명 키입니다.

1. AWS 서비스에서 인증된 요청을 수신하면 요청에 포함된 인증 정보를 사용하여 **서명**을 다시 생성합니다. 서명이 일치하는 경우 서비스에서 요청을 처리합니다. 그렇지 않으면 서비스에서 요청을 거부합니다.

자세한 내용은 [AWS API 요청 서명의 요소](reference_sigv-signing-elements.md) 단원을 참조하십시오.

## AWS SigV4a 작동 방식
<a name="how-sigv4a-works"></a>

SigV4a는 퍼블릭-프라이빗 키 암호화에 기반한 비대칭 서명을 사용합니다. SigV4a는 SigV4와 유사한 범위 지정된 자격 증명 도출 프로세스를 거칩니다. 단, SigV4a는 날짜, 서비스 및 리전을 기반으로 고유한 서명 키를 도출할 필요 없이 동일한 키를 사용하여 모든 요청에 서명합니다. [Elliptic Curve Digital Signature Algorithm](https://csrc.nist.gov/glossary/term/ecdsa)(ECDSA) 키 페어는 기존 AWS 시크릿 액세스 키에서 파생될 수 있습니다.

시스템은 비대칭 암호화를 사용하여 다중 리전 서명을 확인하므로 AWS는 퍼블릭 키만 저장하면 됩니다. 퍼블릭 키는 시크릿이 아니며 요청에 서명하는 데 사용될 수 없습니다. 다중 리전 API 요청에는 비대칭 서명이 필요합니다(예: Amazon S3 다중 리전 액세스 포인트).

다음 단계에서는 SigV4a에서 서명을 계산하는 일반적인 프로세스에 대해 설명합니다.

1. **서명할 문자열**은 요청 유형에 따라 다릅니다. 예를 들어 HTTP Authorization 헤더 또는 쿼리 파라미터를 인증에 사용하는 경우 요청 요소 조합을 사용하여 서명할 문자열을 생성합니다. HTTP POST 요청의 경우 요청의 `POST` 정책은 서명하는 문자열입니다.

1. **서명 키**는 AWS 시크릿 액세스 키에서 각 단계의 결과를 다음 단계에 제공하는 일련의 계산을 통해 도출됩니다. 마지막 단계에서는 키 페어를 생성합니다.

1. AWS 서비스가 Sigv4a로 서명된 요청을 받으면 AWS는 키 페어의 퍼블릭 부분만 사용하여 서명을 확인합니다. 서명이 유효한 경우 요청이 인증되고 서비스가 요청을 처리합니다. 서명이 유효하지 않은 요청은 거부됩니다.

다중 리전 API 요청의 SigV4a에 대한 자세한 내용은 GitHub에서 [sigv4a-signing-examples](https://github.com/aws-samples/sigv4a-signing-examples) 프로젝트를 참조하세요.

## 요청에 서명하는 경우
<a name="when-do-you-need-to-sign"></a>

AWS에 API 요청을 전송하는 사용자 지정 코드를 작성할 때 요청에 서명하는 코드를 포함해야 합니다. 사용자 지정 코드를 작성하는 이유는 다음과 같습니다.
+ AWS SDK가 없는 프로그래밍 언어로 작업하는 경우
+ AWS에 요청을 전송하는 방법을 완벽하게 제어해야 하는 경우

API 요청은 AWS SigV4로 액세스를 인증하는 반면, AWS SDK와 AWS CLI는 사용자가 제공하는 액세스 키를 사용하여 요청을 인증합니다. AWS SDK 및 AWS CLI를 사용한 인증에 대한 자세한 내용은 [추가 리소스](#reference_aws-signing-resources)의 내용을 참조하세요.

## 요청에 서명하는 이유
<a name="why-requests-are-signed"></a>

서명 프로세스는 다음과 같은 방법으로 요청을 보호할 수 있습니다.
+ **요청자의 ID 확인**

  인증된 요청에는 액세스 키(액세스 키 ID, 비밀 액세스 키)를 사용하여 만든 서명이 필요합니다. 임시 보안 인증 정보를 사용하는 경우 서명 계산에 보안 토큰도 필요합니다. 자세한 내용은 [AWS 보안 자격 증명 프로그래밍 방식 액세스](security-creds-programmatic-access.md)를 참조하세요.
+ **전송 중인 데이터 보호**

  요청이 전송되는 동안 훼손되는 것을 방지하기 위해 일부 요청 요소를 사용하여 요청의 해시(다이제스트)를 계산하고 결과 해시 값을 요청의 일부로 포함합니다. AWS 서비스에서는 요청이 수신되면 동일한 정보를 사용하여 해시를 계산한 후 요청에 있는 해시 값과 비교합니다. 값이 일치하지 않으면 AWS에서 요청을 거부합니다.
+ **잠재적 재생 공격으로부터 보호**

  대부분의 경우 요청서의 타임스탬프 시간으로부터 5분 이내에 AWS에 요청이 도착해야 합니다. 그렇지 않으면 AWS가 요청을 거부합니다.

AWS SigV4는 HTTP Authorization 헤더에서 또는 URL의 쿼리 문자열로 표현될 수 있습니다. 자세한 내용은 [인증 방법](reference_sigv-authentication-methods.md) 단원을 참조하십시오.

## 추가 리소스
<a name="reference_aws-signing-resources"></a>
+ 다양한 서비스의 SigV4 서명 프로세스에 대한 자세한 내용은 [서명 요청 예](reference_sigv-examples.md)의 내용을 참조하세요.
+ AWS CLI의 프로그래밍 액세스를 위한 자격 증명을 구성하려면 **AWS 명령줄 인터페이스 사용 설명서의 [인증 및 액세스 자격 증명](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html)을 참조하세요.
+ AWS SDK에는 AWS API 요청에 서명하기 위한 GitHub의 소스 코드가 포함되어 있습니다. 코드 샘플은 [AWS 샘플 리포지토리의 예시 프로젝트](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)

# AWS API 요청 서명의 요소
<a name="reference_sigv-signing-elements"></a>

**중요**  
AWS SDK 또는 CLI를 사용하지 않는 한 요청에 인증 정보를 제공하는 서명을 계산하는 코드를 작성해야 합니다. AWS 서명 버전 4의 서명 계산은 복잡한 작업일 수 있으므로 가능한 경우 AWS SDK 또는 CLI를 사용하는 것이 좋습니다.

서명 버전 4를 사용하는 각 HTTP/HTTPS 요청은 이러한 요소를 반드시 포함해야 합니다.

**Topics**
+ [엔드포인트 사양](#endpoint-specification)
+ [작업](#action)
+ [작업 파라미터](#parameters)
+ [날짜](#date)
+ [인증 정보](#authentication)

## 엔드포인트 사양
<a name="endpoint-specification"></a>

요청을 전송할 엔드포인트의 DNS 이름을 지정합니다. 이 이름에는 일반적으로 서비스 코드와 리전이 포함됩니다. 예를 들어 `us-east-1` 리전에서 Amazon DynamoDB의 엔드포인트는 `dynamodb.us-east-1.amazonaws.com`입니다.

HTTP/1.1 요청의 경우에는 `Host` 헤더를 반드시 포함해야 합니다. HTTP/2 요청의 경우에는 `:authority` 헤더나 `Host` 헤더를 포함할 수 있습니다. HTTP/2 사양의 규정 준수용으로는 `:authority` 헤더만 사용하십시오. 모든 서비스가 HTTP/2 요청을 지원하는 것은 아닙니다.

각 서비스에서 지원하는 엔드포인트에 대한 자세한 내용은 **AWS 일반 참조의 [서비스 엔드포인트 및 할당량](https://docs.aws.amazon.com/general/latest/gr/aws-service-information.html)을 참조하세요.

## 작업
<a name="action"></a>

서비스에 대한 API 작업을 지정합니다. DynamoDB `CreateTable` 작업 또는 Amazon EC2 `DescribeInstances` 작업을 예로 들 수 있습니다.

각 서비스에서 지원하는 작업은 [서비스 승인 참조](https://docs.aws.amazon.com//service-authorization/latest/reference/reference.html)를 참조하세요.

## 작업 파라미터
<a name="parameters"></a>

요청에 지정된 작업의 파라미터를 지정합니다. 각 AWS API 작업에는 필수 및 선택적 파라미터 세트가 있습니다. API 버전은 대부분 필수 파라미터입니다.

API 작업에서 지원하는 파라미터는 해당 서비스의 API 참조를 참조하세요.

## 날짜
<a name="date"></a>

요청의 날짜 및 시간을 지정합니다. 요청에 날짜 및 시간을 포함하면 제3자가 요청을 가로채고 나중에 다시 전송하지 못하도록 차단할 수 있습니다. 보안 인증 범위에 지정하는 날짜는 요청의 날짜와 일치해야 합니다.

타임스탬프는 협정 세계시(UTC)이고 *YYYYMMDD*T*HHMMSS*Z ISO 8601 형식이어야 합니다. 예를 들어 `20220830T123600Z`입니다. 타임스탬프에 밀리초를 포함하지 마십시오.

`date` 또는 `x-amz-date` 헤더를 사용하거나 `x-amz-date`를 쿼리 파라미터로 포함할 수 있습니다. `x-amz-date` 헤더를 찾을 수 없는 경우 `date` 헤더를 찾습니다.

## 인증 정보
<a name="authentication"></a>

사용자가 전송하는 각 요청에는 다음 정보가 포함되어야 합니다. AWS는 이 정보를 사용하여 요청의 유효성 및 진위를 확인합니다.
+ 알고리즘 - 서명 프로세스의 일부로 사용하는 알고리즘.
  + SigV4 - `AWS4-HMAC-SHA256`을 사용하여 `HMAC-SHA256` 해시 알고리즘으로 Signature Version 4를 지정합니다.
  + SigV4a - `AWS4-ECDSA-P256-SHA256`을 사용하여 `ECDSA-P256-SHA-256` 해시 알고리즘을 지정합니다.
+ 자격 증명 - 액세스 키 ID 및 자격 증명 범위 구성 요소를 연결하여 구성된 문자열.
  + SigV4 - 자격 증명 범위에는 액세스 키 ID, *YYYYMMDD* 형식의 날짜, 리전 코드, 서비스 코드, `aws4_request` 종료 문자열(슬래시(/)로 구분됨)이 포함됩니다. 리전 코드, 서비스 코드 및 종료 문자열에는 소문자를 사용해야 합니다.

    ```
    AKIAIOSFODNN7EXAMPLE/YYYYMMDD/region/service/aws4_request
    ```
  + SigV4a - 자격 증명 범위에는 YYYYMMDD 형식의 날짜, 서비스 이름, `aws4_request` 종료 문자열(슬래시(/)로 구분됨)이 포함됩니다. 리전이 별도의 헤더(`X-Amz-Region-Set`)에 포함되므로 자격 증명 범위에는 리전이 포함되지 않습니다.

    ```
    AKIAIOSFODNN7EXAMPLE/YYYYMMDD/service/aws4_request
    ```
+ 서명된 헤더 - 서명에 포함할 HTTP 헤더로, 세미콜론(;)으로 구분됩니다. 예를 들어 `host;x-amz-date`입니다.

  SigV4a의 경우 요청이 유효한 리전 세트를 지정하는 리전 세트 헤더를 포함해야 합니다. `X-Amz-Region-Set` 헤더는 쉼표로 구분된 값 목록으로 지정됩니다. 다음 예제는 us-east-1 및 us-west-1 리전 모두에서 요청을 수행할 수 있는 리전 헤더를 보여줍니다.

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

  리전에서 와일드카드(\$1)를 사용하여 여러 리전을 지정할 수 있습니다. 다음 예제에서 헤더는 us-west-1 및 us-west-2 모두에서 요청을 수행할 수 있도록 허용합니다.

  ```
  X-Amz-Region-Set=us-west-*
  ```
+ 서명 - 계산된 서명을 나타내는 16진수로 인코딩된 문자열입니다. `Algorithm` 파라미터에서 지정한 알고리즘을 사용해 서명을 계산해야 합니다.

자세한 내용은 [인증 방법](reference_sigv-authentication-methods.md) 섹션을 참조하세요.

# 인증 방법
<a name="reference_sigv-authentication-methods"></a>

**중요**  
AWS SDK 또는 CLI를 사용하지 않는 한 요청에 인증 정보를 제공하는 서명을 계산하는 코드를 작성해야 합니다. AWS 서명 버전 4의 서명 계산은 복잡한 작업일 수 있으므로 가능한 경우 AWS SDK 또는 CLI를 사용하는 것이 좋습니다.

다음 방법 중 하나를 사용하여 인증 정보를 표현할 수 있습니다.

## HTTP Authorization 헤더
<a name="aws-signing-authentication-methods-http"></a>

HTTP `Authorization` 헤더는 요청을 인증하는 가장 일반적인 방법입니다. 모든 REST API 작업(`POST`를 사용한 브라우저 기반 업로드 제외)에는 이 헤더가 필요합니다.

다음 예제에서는 SigV4 및 SigV4a에 대한 `Authorization` 헤더 값을 보여줍니다. 가독성을 위해 이 예시에 줄바꿈이 추가됩니다. 코드에서는 헤더가 연속된 문자열이어야 합니다. 알고리즘과 보안 인증 정보 사이에는 쉼표가 없지만 다른 요소는 쉼표로 구분해야 합니다.

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

다음 표에서는 앞선 예제에 있는 Authorization 헤더 값의 다양한 구성 요소를 설명합니다.


| 구성 요소 | 설명 | 
| --- | --- | 
|  권한 부여  | 서명을 계산하는 데 사용된 알고리즘입니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/reference_sigv-authentication-methods.html)  | 
|  자격 증명  |  액세스 키 ID 및 범위 정보. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/reference_sigv-authentication-methods.html) <date> 값은 YYYYMMDD 형식을 사용하여 지정됩니다. Amazon S3로 요청을 보낼 때 <aws-service> 값은 S3입니다.  | 
|  SignedHeaders  |   서명 계산에 사용된 세미콜론으로 구분된 요청 헤더의 목록. 목록에는 헤더 이름만 포함되며, 헤더 이름은 소문자여야 합니다. 예: `host;range;x-amz-date` SigV4a의 경우 요청이 유효한 리전 세트를 지정하는 리전 세트 헤더를 포함해야 합니다. X-Amz-Region-Set 헤더는 쉼표로 구분된 값 목록으로 지정됩니다.  | 
|  서명  |  64개의 소문자 16진수 문자로 표현되는 256비트 서명. 예:`fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024` 서명 계산은 페이로드를 전송하기 위해 선택한 옵션에 따라 달라집니다.  | 

## 쿼리 문자열 파라미터
<a name="aws-signing-authentication-methods-query"></a>

쿼리 문자열을 사용하여 전체 요청을 URL로 표현할 수 있습니다. 이 경우 쿼리 파라미터를 사용하여 인증 정보를 포함한 요청 정보를 제공합니다. 요청 서명이 URL의 일부이므로 이 URL 유형을 미리 서명된 URL이라고 합니다. 미리 서명된 URL을 사용하여 최대 7일 동안 유효할 수 있는 클릭 가능한 링크를 HTML에 포함할 수 있습니다. 자세한 내용은 *Amazon S3 API 참조*의 [Authenticating Requests: Using Query Parameters(AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html)를 참조하세요.

다음 예제에서는 SigV4 및 SigV4a에 대해 미리 서명된 URL을 보여줍니다. 가독성을 위해 이 예시에 줄바꿈이 추가됩니다.

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

**참고**  
URL의 `X-Amz-Credential` 값은 가독성을 위해 ‘/’ 문자만 표시합니다. 실제로는 %2F로 인코딩되어야 합니다. 예제:  
`&X-Amz-Credential=<your-access-key-id>%2F20130721%2Fus-east-1%2Fs3%2Faws4_request`

다음 표에서는 인증 정보를 제공하는 URL의 쿼리 파라미터를 설명합니다.


| 쿼리 문자열 파라미터 이름 | 설명 | 
| --- | --- | 
|  X-Amz-Algorithm  |  서명 계산에 사용된 AWS 서명 버전 및 알고리즘을 식별합니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/reference_sigv-authentication-methods.html)  | 
|  X-Amz-Credential  |  이 파라미터는 액세스 키 ID 외에도 서명이 유효한 범위를 제공합니다. 이 값은 다음 섹션의 설명과 같이 서명 계산에 사용하는 범위와 일치해야 합니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/reference_sigv-authentication-methods.html) AWS 리전 문자열 목록은 **AWS 일반 참조의 [Regional Endpoints](https://docs.aws.amazon.com//general/latest/gr/rande.html#regional-endpoints)를 참조하세요.  | 
|  X-Amz-Region-Set  |  요청이 유효한 리전 세트. x-amz-region-set 헤더는 쉼표로 구분된 값 목록으로 지정됩니다.  | 
|  X-Amz-Date  |  날짜 및 시간 형식은 ISO 8601 표준을 따르고, `yyyyMMddTHHmmssZ` 형식을 사용해야 합니다. 예를 들어 날짜와 시간이 ‘08/01/2016 15:32:41.982-700’인 경우 UTC(협정 세계시)로 변환하여 ‘20160801T223241Z’로 제출해야 합니다.  | 
|  X-Amz-Expires  |  생성된 미리 서명된 URL이 유효한 기간(초)을 제공합니다. 예: 86400(24시간). 이 값은 정수입니다. 설정할 수 있는 최솟값은 1이고, 최댓값은 604800(7일)입니다. 서명 계산에 사용하는 서명 키는 최대 7일 동안 유효하므로 미리 서명된 URL은 최대 7일 동안 유효할 수 있습니다.  | 
|  X-Amz-SignedHeaders  |  서명 계산에 사용한 헤더를 나열합니다. 서명 계산에는 다음 헤더가 필요합니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/reference_sigv-authentication-methods.html) 보안을 강화하려면 요청에 포함하려는 모든 요청 헤더에 서명해야 합니다.  | 
|  X-Amz-Signature  |  요청을 인증하기 위한 서명을 제공합니다. 이 서명은 서비스에서 계산하는 서명과 일치해야 합니다. 그렇지 않으면 서비스가 요청을 거부합니다. 예: `733255ef022bec3f2a8701cd61d4b371f3f28c9f193a1f02279211d48d5193d7` 서명 계산은 다음 섹션에서 설명합니다.  | 
|  X-Amz-Security-Token  |  STS 서비스에서 가져온 보안 인증 정보를 사용하는 경우의 선택적 보안 자격 증명 파라미터입니다.  | 

# 서명된 AWS API 요청 생성
<a name="reference_sigv-create-signed-request"></a>

**중요**  
AWS SDK([샘플 코드 및 라이브러리](https://aws.amazon.com/developer/) 참조) 또는 AWS Command Line Interface(AWS CLI) 도구를 사용하여 API 요청을 AWS로 전송하는 경우 SDK 및 CLI 클라이언트는 사용자 요청 인증에 사용자가 제공한 액세스 키를 사용하므로 이 섹션을 건너뛰어도 됩니다. 그럴 만한 이유가 없는 경우 항상 SDK 또는 CLI를 사용하는 것이 좋습니다.  
여러 서명 버전을 지원하는 리전에서는 수동 서명을 요청하는 경우 사용할 서명 버전을 지정해야 합니다. 다중 리전 액세스 포인트로 요청을 공급하는 경우 SDK와 CLI가 자동으로 추가 구성 없이 서명 버전 4A를 사용하는 것으로 전환됩니다.

AWS SigV4 서명 프로토콜을 사용하여 AWS API 요청에 대한 서명된 요청을 생성할 수 있습니다.

1. 요청 세부 정보를 기반으로 표준 요청 생성.

1. AWS 자격 증명을 사용하여 서명 계산.

1. 이 서명을 요청에 Authorization 헤더로 추가.

AWS에서는 이 프로세스를 복제하고 서명을 확인하여 그에 따라 액세스를 허용하거나 거부합니다.

AWS SigV4를 사용하여 API 요청에 서명하는 방법은 [서명 요청 예](reference_sigv-examples.md) 섹션을 참조하세요.

다음 표에서는 서명된 요청을 생성하는 과정에서 사용되는 함수를 설명합니다. 이러한 함수의 코드를 구현해야 합니다. 자세한 내용은 [AWS SDK의 코드 예제](reference_sigv.md#reference_aws-signing-resources)를 참조하세요.


| 함수 | 설명 | 
| --- | --- | 
|  `Lowercase()`  |  문자열을 소문자로 변환합니다.  | 
|  `Hex()`  |  소문자 16진법 인코딩.  | 
|  `SHA256Hash()`  |  보안 해시 알고리즘(SHA) 암호화 해시 함수.  | 
|  `HMAC-SHA256()`  |  제공된 서명 키를 포함한 SHA256 알고리즘을 사용하여 HMAC를 계산합니다. SigV4로 서명하는 경우 최종 서명입니다.  | 
|  `ECDSA-Sign`  |  퍼블릭-프라이빗 키 암호화를 기반으로 비대칭 서명을 사용해 계산된 타원 곡선 디지털 서명 알고리즘(ECDSA) 서명.  | 
|  `KDF(K, Label, Context, L)`  |  [NIST SP 800-108r1](https://doi.org/10.6028/NIST.SP.800-108r1-upd1)에 정의된 대로, PRF 함수 HMAC-SHA256을 사용하는 카운터 모드의 NIST SP800-108 KDF.  | 
|  `Oct2Int(byte[ ])`  |  ANSI X9.62에 설명된 대로, 옥텟 대 정수 함수.  | 
|  `Trim()`  |  선행 또는 후행 공백을 모두 제거합니다.  | 
|  `UriEncode()`  |  URI는 모든 바이트를 인코딩합니다. UriEncode()는 다음 규칙을 적용해야 합니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/reference_sigv-create-signed-request.html)  개발 플랫폼에서 제공하는 표준 UriEncode 함수는 구현상의 차이와 기본 RFC의 관련 모호성으로 인해 효과적이지 않을 수 있습니다. 인코딩이 제대로 작동하도록 사용자 지정 UriEncode 함수를 직접 작성하는 것이 좋습니다.  Java에서 UriEncode 함수의 예를 보려면 GitHub 웹사이트에서 [Java 유틸리티](https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/util/SdkHttpUtils.java#L66)를 참조하세요.  | 

**참고**  
요청에 서명할 때 AWS SigV4 또는 AWS SigV4a를 사용할 수 있습니다. 둘 사이의 주요 차이점은 서명 계산 방법에 따라 결정됩니다. SigV4a를 사용하면 리전 세트가 서명할 문자열에 포함되지만 자격 증명 파생 단계의 일부는 아닙니다.

## 임시 보안 자격 증명을 사용하여 요청 서명
<a name="temporary-security-credentials"></a>

장기 보안 인증 정보를 사용하여 요청에 서명하는 대신 AWS Security Token Service(AWS STS)에서 제공하는 임시 보안 인증 정보를 사용할 수 있습니다.

임시 보안 자격 증명을 사용하는 경우 Authorization 헤더 또는 쿼리 문자열에 `X-Amz-Security-Token`을 추가하거나 포함하여 세션 토큰을 저장해야 합니다. 일부 서비스의 경우 표준 요청에 `X-Amz-Security-Token`을 추가해야 합니다. 다른 서비스의 경우, 서명을 계산한 후에 `X-Amz-Security-Token`을 끝에 추가하기만 하면 됩니다. 구체적인 요구 사항은 각 AWS 서비스의 설명서를 참조하세요.

## 서명 단계 요약
<a name="create-signed-request-steps"></a>

**표준 요청 생성**  
요청 내용(호스트, 작업, 헤더 등)을 표준 형식으로 정렬합니다. 표준 요청은 서명할 문자열을 생성하는 데 사용되는 입력 중 하나입니다. 표준 요청 생성에 대한 자세한 내용은 [AWS API 요청 서명의 요소](reference_sigv-signing-elements.md)의 내용을 참조하세요.

**표준 요청의 해시 생성**  
페이로드의 해시를 생성하는 데 사용한 것과 동일한 알고리즘을 사용하여 표준 요청을 해시합니다. 표준 요청의 해시는 소문자 16진수 문자의 문자열입니다.

**서명할 문자열 생성**  
표준 요청과 추가 정보(예: 알고리즘, 요청 날짜, 자격 증명 범위, 표준 요청의 해시)를 사용하여 서명할 문자열을 생성합니다.

**서명 키 추출**  
시크릿 액세스 키를 사용하여 요청에 서명하는 데 사용되는 키를 파생합니다.

**서명 계산**  
파생된 서명 키를 해시 키로 사용하여 서명할 문자열에서 키가 추가된 해시 작업을 수행합니다.

**요청에 서명 추가**  
HTTP 헤더 또는 요청의 쿼리 문자열에 계산된 서명을 추가합니다.

## 표준 요청 생성
<a name="create-canonical-request"></a>

표준 요청을 생성하려면 다음 문자열을 줄 바꿈 문자로 구분해 연결합니다. 이렇게 하면 사용자가 계산하는 서명이 AWS에서 계산하는 서명과 일치하도록 할 수 있습니다.

```
<HTTPMethod>\n
<CanonicalURI>\n
<CanonicalQueryString>\n
<CanonicalHeaders>\n
<SignedHeaders>\n
<HashedPayload>
```
+ *HTTPMethod* - HTTP 메서드(예:`GET`, `PUT`, `HEAD` 및 `DELETE`).
+ *CanonicalUri* – 도메인 이름 뒤에 오는 `/` 문자로 시작하여 문자열의 끝 또는 쿼리 문자열 파라미터가 있는 경우 물음표 문자(`?`)까지의 절대 경로 구성 요소 URI의 URI 인코딩 버전입니다. 절대 경로가 비어있는 경우, 슬래시 문자(`/`)를 사용합니다. 다음 예제에서 URI `/amzn-s3-demo-bucket/myphoto.jpg`는 절대 경로이며 절대 경로에는 `/` 문자를 인코딩하지 않습니다.

  ```
  http://s3.amazonaws.com/amzn-s3-demo-bucket/myphoto.jpg
  ```
+ *CanonicalQueryString* - URI 인코딩 쿼리 문자열 파라미터. 각 이름과 값을 개별적으로 URI 인코딩합니다. 또한 표준 쿼리 문자열의 파라미터를 키 이름별로 알파벳순으로 정렬해야 합니다. 정렬은 인코딩 후에 이루어집니다. 다음 URI 예제의 쿼리 문자열은 다음과 같습니다.

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

  표준 쿼리 문자열은 다음과 같습니다(가독성을 위해 줄바꿈 추가됨).

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

  요청이 하위 리소스를 대상으로 하는 경우 해당 쿼리 파라미터 값은 빈 문자열(`""`)이 됩니다. 예를 들어, 다음 URI는 `amzn-s3-demo-bucket` 버킷에서 `ACL` 하위 리소스를 식별합니다.

   

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

  이 경우 CanonicalQueryString은 다음과 같습니다.

   

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

  URI에 `?` 문자가 포함되지 않은 경우 요청에는 쿼리 문자열이 없으며, 표준 쿼리 문자열을 빈 문자열(`""`)로 설정합니다. 여전히 줄 바꿈 문자(`"\n"`)를 포함해야 합니다.
+ *CanonicalHeaders* - 요청 헤더와 해당 값이 포함된 목록. 개별 헤더 이름과 값 페어는 줄 바꿈 문자(`"\n"`)로 구분됩니다. 다음은 CanonicalHeader의 예제입니다.

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

  CanonicalHeaders 목록에는 다음이 포함되어야 합니다.
  + HTTP `host` 헤더
  + `Content-Type` 헤더가 요청에 있는 경우 이를 *CanonicalHeaders* 목록에 추가해야 합니다.
  + 요청에 포함할 `x-amz-*` 헤더 또한 추가되어야 합니다. 예를 들어, 임시 보안 인증 정보를 사용하는 경우 요청에 `x-amz-security-token`을 포함해야 합니다. 이 헤더를 *CanonicalHeaders* 목록에 추가해야 합니다.
  + SigV4a의 경우 요청이 유효한 리전 세트를 지정하는 리전 세트 헤더를 포함해야 합니다. `X-Amz-Region-Set` 헤더는 쉼표로 구분된 값 목록으로 지정됩니다. 다음 예제는 us-east-1 및 us-west-1 리전 모두에서 요청을 수행할 수 있는 리전 헤더를 보여줍니다.

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

    리전에서 와일드카드(\$1)를 사용하여 여러 리전을 지정할 수 있습니다. 다음 예제에서 헤더는 us-west-1 및 us-west-2 모두에서 요청을 수행할 수 있도록 허용합니다.

    `X-Amz-Region-Set=us-west-*`
**참고**  
Amazon S3 AWS 요청에는 `x-amz-content-sha256` 헤더가 필요합니다. 요청 페이로드의 해시를 제공합니다. 페이로드가 없는 경우 빈 문자열의 해시를 제공해야 합니다.

  각 헤더 이름은 다음과 같아야 합니다.
  + 소문자를 사용합니다.
  + 알파벳 순서로 표시됩니다.
  + 뒤에 콜론(`:`)이 와야 합니다.

  값의 경우 다음을 수행해야 합니다.
  + 선행 또는 후행 공백을 모두 잘라냅니다.
  + 순차적 공백을 단일 공백으로 변환합니다.
  + 쉼표를 사용하여 다중 값 헤더의 값을 구분합니다.
  + host 헤더(HTTP/1.1) 또는 :authority 헤더(HTTP/2) 및 모든 `x-amz-*` 헤더를 서명에 포함해야 합니다. 서명에 content-type과 같은 다른 표준 헤더를 선택적으로 포함할 수 있습니다.

  이 예제에서 사용하는 `Lowercase()` 및 `Trim()` 함수는 이전 섹션에서 설명합니다.

  다음은 `CanonicalHeaders` 문자열의 예입니다. 헤더 이름은 소문자이고 정렬되어 있습니다.

   

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

   
**참고**  
권한 부여 서명을 계산하기 위해 호스트와 `x-amz-*` 헤더만 필요합니다. 하지만 데이터 변조 방지를 위해 서명 계산에 추가 헤더를 포함하는 것이 좋습니다.  
복잡한 시스템에서 전송 중 자주 변경되는 hop-by-hop 헤더를 포함하지 마세요. 여기에는 `connection`, `x-amzn-trace-id`, `user-agent`, `keep-alive`, `transfer-encoding`, `TE`, `trailer`, `upgrade`, `proxy-authorization`, `proxy-authenticate`를 포함하여 프록시, 로드 밸런서 및 분산 시스템의 노드에 의해 변경되는 모든 휘발성 전송 헤더가 포함됩니다.
+ *SignedHeaders* - 알파벳순으로 정렬되고 세미콜론으로 구분된 소문자 요청 헤더 이름 목록입니다. 목록의 요청 헤더는 `CanonicalHeaders` 문자열에 포함한 것과 동일합니다. 이전 예제에서 *SignedHeaders*의 값은 다음과 같습니다.

  ```
  host;x-amz-content-sha256;x-amz-date
  ```
+ *HashedPayload* - HTTP 요청 본문의 페이로드를 해시 함수의 입력으로 사용하여 생성된 문자열입니다. 이 문자열은 소문자 16진수 문자를 사용합니다.

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

  요청에 페이로드가 없는 경우 빈 문자열의 해시를 계산합니다. 예를 들어, `GET` 요청을 사용하여 객체를 검색하는 경우 페이로드에 아무 것도 없습니다.

  ```
  Hex(SHA256Hash(""))
  ```
**참고**  
Amazon S3의 경우 표준 요청을 생성할 때 리터럴 문자열 `UNSIGNED-PAYLOAD`를 포함하고, 요청을 보낼 때는 `x-amz-content-sha256` 헤더 값과 동일한 값을 설정합니다.  
`Hex(SHA256Hash("UNSIGNED-PAYLOAD"))`

## 표준 요청의 해시 생성
<a name="create-canonical-request-hash"></a>

페이로드의 해시를 생성하는 데 사용한 것과 동일한 알고리즘을 사용하여 표준 요청의 해시(다이제스트)를 생성합니다. 표준 요청의 해시는 소문자 16진수 문자의 문자열입니다.

## 서명할 문자열 생성
<a name="create-string-to-sign"></a>

서명할 문자열을 생성하려면 다음 문자열을 줄 바꿈 문자로 구분하여 연결합니다. 이 문자열을 줄 바꿈 문자로 끝내지 마세요.

```
Algorithm \n
RequestDateTime \n
CredentialScope  \n
HashedCanonicalRequest
```
+ *Algorithm* - 표준 요청의 해시를 생성하는 데 사용되는 알고리즘입니다.
  + SigV4 - `AWS4-HMAC-SHA256`을 사용하여 `HMAC-SHA256` 해시 알고리즘을 지정합니다.
  + SigV4a - `AWS4-ECDSA-P256-SHA256`을 사용하여 `ECDSA-P256-SHA-256` 해시 알고리즘을 지정합니다.
+ *RequestDateTime* - 보안 인증 범위에 사용된 날짜 및 시간입니다. 이 값은 ISO 8601 형식의 현재 UTC 시간입니다 (예: `20130524T000000Z`).
+ *CredentialScope* - 결과로 나오는 서명을 지정된 리전 및 서비스로 제한하는 자격 증명 범위입니다.
  + SigV4 - 자격 증명에는 액세스 키 ID, `YYYYMMDD` 형식의 날짜, 리전 코드, 서비스 코드, `aws4_request` 종료 문자열(슬래시(/)로 구분됨)이 포함됩니다. 리전 코드, 서비스 코드 및 종료 문자열에는 소문자를 사용해야 합니다. 이 문자열의 형식은 `YYYYMMDD/region/service/aws4_request`와 같습니다.
  + SigV4a - 자격 증명에는 `YYYYMMDD` 형식의 날짜, 서비스 이름, `aws4_request` 종료 문자열(슬래시(/)로 구분됨)이 포함됩니다. 리전이 별도의 헤더(`X-Amz-Region-Set`)에 포함되므로 자격 증명 범위에는 리전이 포함되지 않습니다. 이 문자열의 형식은 `YYYYMMDD/service/aws4_request`와 같습니다.
+ *HashedCanonicalRequest* - 이전 단계에서 계산된 표준 요청의 해시입니다.

다음은 서명할 문자열의 예입니다.

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

## 서명 키 추출
<a name="derive-signing-key"></a>

서명 키를 파생하려면 다음 프로세스 중 하나를 선택하여 SigV4 또는 SigV4a의 서명 키를 계산합니다.

### SigV4에 대한 서명 키 파생
<a name="derive-signing-key-sigv4"></a>

SigV4에 대한 서명 키를 파생하기 위해 AWS 시크릿 액세스 키를 초기 해시 작업에 대한 키로 사용하여 요청 날짜, 리전 및 서비스에 대해 일련의 키가 추가된 해시 작업(HMAC)을 수행합니다.

각 단계마다 필요한 키와 데이터를 사용하여 해시 함수를 호출합니다. 해시 함수에 대한 각 호출의 결과는 다음 해시 함수 호출의 입력이 됩니다.

다음 예제는 이 절차의 다음 섹션에서 사용된 `SigningKey` 추출 방법을 보여주며, 입력이 연결되고 해시되는 순서를 보여줍니다. 보이는 것처럼 `HMAC-SHA256`은 데이터를 해시하는 데 사용되는 해시 함수입니다.

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

**필수 입력**
+ `Key` - 시크릿 액세스 키를 포함하는 문자열.
+ `Date` - 자격 증명 범위에 사용되는 날짜(*YYYYMMDD* 형식)를 포함하는 문자열.
+ `Region` - 리전 코드(예: `us-east-1`)를 포함하는 문자열.

  리전 문자열 목록은 **AWS 일반 참조의 [리전 엔드포인트](https://docs.aws.amazon.com//general/latest/gr/rande.html#regional-endpoints)를 참조하세요.
+ `Service` - 서비스 코드(예: `ec2`)를 포함하는 문자열.
+ 이전 단계에서 생성한 서명할 문자열입니다.

**SigV4에 대한 서명 키를 파생하는 방법**

1. `"AWS4"`와 비밀 액세스 키를 연결합니다. 연결된 문자열을 키로, 날짜 문자열을 데이터로 각각 사용하여 해시 함수를 호출합니다.

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

1. 이전 호출의 결과를 키로, 리전 문자열을 데이터로 각각 사용하여 해시 함수를 호출합니다.

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

1. 이전 호출의 결과를 키로, 서비스 문자열을 데이터로 각각 사용하여 해시 함수를 호출합니다.

   서비스 코드는 서비스에 의해 정의합니다. **AWS Pricing CLI의 [get-products](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/pricing/get-products.html)를 사용하여 서비스의 서비스 코드를 반환할 수 있습니다.

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

1. 이전 호출의 결과를 키로, ‘aws4\$1request’를 데이터로 각각 사용하여 해시 함수를 호출합니다.

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

### SigV4a에 대한 서명 키 파생
<a name="derive-signing-key-sigv4a"></a>

SigV4a에 대한 서명 키를 생성하려면 다음 프로세스를 사용하여 시크릿 액세스 키에서 키 페어를 파생합니다. 이 파생 구현의 예제는 [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
}
```

## 서명 계산
<a name="calculate-signature"></a>

서명 키를 파생한 후에는 요청에 추가할 서명을 계산합니다. 이 절차는 사용하는 서명 버전에 따라 달라집니다.

**SigV4에 대한 서명을 계산하는 방법**

1. 이전 직접 호출의 결과를 키로, **서명할 문자열**을 데이터로 각각 사용하여 해시 함수를 직접 호출하세요. 파생된 서명 키를 이 작업에 대한 해시 키로 사용합니다. 이진수 값 형식의 서명이 결과로 반환됩니다.

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

1. 서명을 이진수에서 소문자의 16진수 표현으로 변환합니다.

**SigV4a에 대한 서명을 계산하는 방법**

1. 디지털 서명 알고리즘(ECDSA P-256)을 사용하여 이전 단계에서 생성한 **서명할 문자열**로 서명합니다. 이 서명에 사용되는 키는 위에서 설명한 시크릿 액세스 키에서 파생된 프라이빗 비대칭 키입니다.

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

1. 서명을 이진수에서 소문자의 16진수 표현으로 변환합니다.

## 요청에 서명 추가
<a name="add-signature-to-request"></a>

계산된 서명을 요청에 추가합니다.

**Example 예: 인증 헤더**  
**SigV4**  
다음 예제에서는 AWS SigV4를 사용하는 `DescribeInstances` 작업에 대한 `Authorization` 헤더를 보여줍니다. 이 예에서는 가독성을 높이기 위해 줄 바꿈을 사용했습니다. 코드에서는 이 문자열이 연속된 문자열이어야 합니다. 알고리즘과 `Credential` 사이에 쉼표는 없습니다. 단, 다른 요소는 쉼표로 구분해야 합니다.

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

**SigV4a**  
다음 예제에서는 AWS SigV4a를 사용하는 `CreateBucket` 작업에 대한 권한 부여 헤더를 보여줍니다. 이 예에서는 가독성을 높이기 위해 줄 바꿈을 사용했습니다. 코드에서는 이 문자열이 연속된 문자열이어야 합니다. 알고리즘과 자격 증명 사이에 쉼표는 없습니다. 단, 다른 요소는 쉼표로 구분해야 합니다.

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

**Example 예: 쿼리 문자열에 인증 파라미터가 있는 요청**  
**SigV4**  
다음 예제에서는 인증 정보가 포함된 AWS SigV4를 사용하는 `DescribeInstances` 작업에 대한 쿼리를 보여줍니다. 이 예에서는 가독성을 높이기 위해 줄 바꿈을 사용했으며 URL로 인코딩하지 않았습니다. 코드에서 이 쿼리 문자열은 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**  
다음 예제에서는 인증 정보가 포함된 AWS SigV4a를 사용하는 `CreateBucket` 작업에 대한 쿼리를 보여줍니다. 이 예에서는 가독성을 높이기 위해 줄 바꿈을 사용했으며 URL로 인코딩하지 않았습니다. 코드에서 이 쿼리 문자열은 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
```

# 서명 요청 예
<a name="reference_sigv-examples"></a>

다음 AWS 서명 요청 예는 SigV4를 사용하여 AWS SDK 또는 AWS 명령줄 도구 없이 전송된 요청에 서명하는 방법을 보여줍니다.

## HTTP POST를 사용한 브라우저 기반 Amazon S3 업로드
<a name="signature-v4-examples-s3-browser"></a>

 [요청 인증: 브라우저 기반 업로드](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html)에서는 Amazon S3가 요청 수신 시 서명을 계산하는 데 사용하는 서명 및 관련 정보를 설명합니다.

[예: HTTP POST를 사용한 브라우저 기반 업로드(AWS Signature Version 4 사용)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html)에서는 샘플 POST 정책 및 파일 업로드에 사용할 수 있는 양식과 함께 자세한 정보를 제공합니다. 예제 정책과 가상 보안 인증 정보는 워크플로와 그에 따른 서명 및 정책 해시를 보여줍니다.

## VPC Lattice 인증 요청
<a name="signature-v4-examples-lattice"></a>

 [Signature Version 4(SigV4) 인증 요청의 예](https://docs.aws.amazon.com/vpc-lattice/latest/ug/sigv4-authenticated-requests.html)에서는 사용자 지정 인터셉터를 사용하거나 사용하지 않고 요청 서명을 수행하는 방법을 보여주는 Python 및 Java 예제를 제공합니다.

## Amazon Translate에서 Signature Version 4 사용
<a name="signature-v4-examples-translate"></a>

 [Live Translations in the Metaverse](https://aws.amazon.com/blogs/spatial/live-translations-in-the-metaverse/)에서는 실시간에 가까운 번역 솔루션을 생성하는 애플리케이션을 빌드하는 방법을 보여줍니다. 이 음성-음성 번역 솔루션은 이벤트 스트림 인코딩에서 AWS SigV4를 사용하여 실시간 트랜스크립션을 생성합니다.

## Neptune에서 Signature Version 4 사용
<a name="signature-v4-examples-neptune"></a>

[예: Signature Version 4 서명으로 Python을 사용하여 Neptune에 연결](https://docs.aws.amazon.com/neptune/latest/userguide/iam-auth-connecting-python.html)에서는 Python을 사용하여 Neptune에 서명된 요청을 보내는 방법을 보여줍니다. 이 예에는 액세스 키 또는 임시 보안 인증 정보를 사용하기 위한 변형이 포함되어 있습니다.

## Amazon Glacier에 대한 HTTP 요청 서명
<a name="signature-v4-examples-streaming-glacier"></a>

[스트리밍 API의 서명 계산 예시](https://docs.aws.amazon.com/amazonglacier/latest/dev/amazon-glacier-signing-requests.html)는 Amazon Glacier의 두 스트리밍 API 중 하나인 아카이브 업로드(POST 아카이브) 서명을 만드는 세부 사항을 안내합니다.

## Amazon SWF에 대한 HTTP 요청 만들기
<a name="signature-v4-examples-swf"></a>

[Amazon SWF에 대한 HTTP 요청 만들기](https://docs.aws.amazon.com/amazonswf/latest/developerguide/UsingJSON-swf.html#HTTPHeader)는 Amazon SWF에 대한 JSON 요청의 헤더 내용을 보여줍니다.

## Amazon OpenSearch Service의 스트리밍 API에 대한 서명 계산
<a name="signature-v4-examples-open-search"></a>

[PHP 버전 3용 AWS SDK로 Amazon OpenSearch Service 검색 요청 서명하기](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/service_es-data-plane.html)에는 Amazon OpenSearch Service에 서명된 HTTP 요청을 보내는 방법에 대한 예시가 포함되어 있습니다.

## AWS 샘플 리포지토리의 예시 프로젝트
<a name="signature-v4-examples-sdk"></a>

다음 예시 프로젝트에서는 Python, Node.js, Java, C\$1, Go 및 Rust와 같은 공통 언어를 사용하는 AWS 서비스에 대해 Rest API 요청을 만들기 위해 요청에 서명하는 방법을 보여줍니다.

### Signature 버전 4a 프로젝트
<a name="signature-v4-examples-sigv4a"></a>

[sigv4-signing-examples](https://github.com/aws-samples/sigv4-signing-examples) 프로젝트는 Python, Node.js, Java, C\$1, Go, Rust와 같은 일반 언어를 사용하는 AWS 서비스에 대해 Rest API 요청을 만들기 위해 SigV4로 요청에 서명하는 방법의 예제를 제공합니다.

[sigv4a-signing-examples](https://github.com/aws-samples/sigv4a-signing-examples) 프로젝트는 다중 리전 API 요청에 서명하는 예를 제공합니다(예: [Amazon S3의 다중 리전 액세스 포인트](https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiRegionAccessPoints.html)).

### AWS IoT Core에 게시
<a name="signature-v4-examples-iot-python"></a>

[HTTPs 프로토콜을 사용하여 AWS IoT Core에 게시하는 Python 코드](https://github.com/aws-samples/aws-iot-core-python-node-sigv4-https)는 HTTPS 프로토콜 및 AWS SigV4 인증을 사용하여 AWS IoT Core에 메시지를 게시하는 방법에 대한 지침을 제공합니다. 두 가지 참조 구현이 있으며 하나는 Python, 다른 하나는 NodeJ로 되어 있습니다.

[HTTPs 프로토콜을 사용하여 AWS IoT Core에 게시하는 .Net Framework 애플리케이션](https://github.com/aws-samples/aws-iot-core-http-sigv4-dotnet-app)은 HTTPS 프로토콜 및 AWS SigV4 인증을 사용하여 AWS IoT Core에 메시지를 게시하는 방법에 대한 지침을 제공합니다. 이 프로젝트에는 .NET 코어에 상응하는 구현도 포함되어 있습니다.

# AWS API 요청에 대한 Signature Version 4 서명 문제 해결
<a name="reference_sigv-troubleshooting"></a>

**중요**  
AWS SDK 또는 CLI를 사용하지 않는 한 요청에 인증 정보를 제공하는 서명을 계산하는 코드를 작성해야 합니다. SigV4 서명 계산은 복잡한 작업일 수 있으므로 가능한 경우 AWS SDK 또는 CLI를 사용하는 것이 좋습니다.

서명된 요청을 생성하는 코드를 개발할 때, AWS 서비스에서 HTTP 403 `SignatureDoesNotMatch`가 발생할 수 있습니다. 이 오류는 AWS에 대한 HTTP 요청의 서명 값이 AWS 서비스에서 계산한 서명과 일치하지 않음을 의미합니다. 권한에서 호출자의 요청을 허용하지 않는 경우 HTTP 401 `Unauthorized` 오류가 반환됩니다.

다음과 같은 경우 API 요청에서 오류가 반환될 수 있습니다.
+ API 요청이 서명되지 않았으며 API 요청이 IAM 인증을 사용합니다.
+ 요청에 서명하는 데 사용된 IAM 보안 인증이 잘못되었거나 API를 간접적으로 호출할 권한이 없습니다.
+ 서명된 API 요청의 서명이 AWS 서비스에서 계산한 서명과 일치하지 않습니다.
+ API 요청 헤더가 잘못되었습니다.

**참고**  
다른 오류 해결 방법을 살펴보기 전에 AWS Signature Version 2(SigV2)에서 AWS Signature Version 4(SigV4)로 서명 프로토콜을 업데이트합니다. Amazon S3 등의 서비스와 리전은 더 이상 SIGv2 서명을 지원하지 않습니다.

**Topics**
+ [보안 인증 오류](#signature-v4-troubleshooting-credential)
+ [표준 요청 및 서명 문자열 오류](#signature-v4-troubleshooting-canonical-errors)
+ [보안 인증 범위 오류](#signature-v4-troubleshooting-credential-scope)
+ [키 서명 오류](#signature-v4-troubleshooting-key-signing)

## 보안 인증 오류
<a name="signature-v4-troubleshooting-credential"></a>

API 요청이 SigV4로 서명되었는지 확인합니다. API 요청이 서명되지 않은 경우 다음과 같은 오류가 발생할 수 있습니다. `Missing Authentication Token`. [누락된 서명을 추가](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html#add-signature-to-request)하고 요청을 다시 전송합니다.

액세스 키 및 비밀 키의 보안 인증이 올바른지 확인합니다. 액세스 키가 잘못된 경우 다음과 같은 오류가 발생할 수 있습니다. `Unauthorized`. 요청에 서명하는 데 사용된 엔터티에 요청을 할 권한이 있는지 확인합니다. 자세한 내용은 [액세스 거부 오류 메시지 문제 해결](troubleshoot_access-denied.md)을 참조하세요.

## 표준 요청 및 서명 문자열 오류
<a name="signature-v4-troubleshooting-canonical-errors"></a>

[표준 요청의 해시 생성](reference_sigv-create-signed-request.md#create-canonical-request-hash) 또는 [서명할 문자열 생성](reference_sigv-create-signed-request.md#create-string-to-sign)에서 표준 요청을 잘못 계산한 경우 서비스에서 수행되는 서명 검증 단계가 실패하고 다음 오류 메시지가 표시됩니다.

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

AWS 서비스에서 서명된 요청을 수신하면 서명을 다시 계산합니다. 값에 차이가 있으면 서명이 일치하지 않는 것입니다. 표준 요청 및 서명된 요청의 문자열을 오류 메시지의 값과 비교합니다. 차이가 있는 경우 서명 프로세스를 수정합니다.

**참고**  
헤더 또는 요청을 수정하는 프록시를 통해 요청을 전송하지 않았는지 확인할 수도 있습니다.

**Example 정식 요청 예**  

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

비밀 키가 액세스 키 ID와 일치하는지 확인하려면, 정상적으로 작동하는 것으로 알려진 구현을 사용하여 비밀 키를 테스트합니다. 예를 들어 AWS SDK 또는 AWS CLI를 사용하여 AWS에 대한 요청을 보냅니다.

### API 요청 헤더
<a name="signature-v4-troubleshooting-credential-header"></a>

인증 헤더가 비어 있거나, 자격 증명 키 또는 서명이 없거나 올바르지 않거나, 헤더가 알고리즘 이름으로 시작하지 않거나, 키 값 쌍에 등호가 포함되지 않은 경우 다음 오류 중 하나가 발생합니다.
+ 인증 헤더는 비워 둘 수 없습니다.
+ 인증 헤더에는 '자격 증명' 매개변수가 필요합니다.
+ 인증 헤더에는 '서명' 매개변수가 필요합니다.
+ 인증 헤더에서 잘못된 키=값 쌍(등호 누락)이 서명에 포함되어 있습니다.

[서명 계산](reference_sigv-create-signed-request.md#calculate-signature)에서 추가한 SigV4 인증 헤더에 올바른 자격 증명 키가 포함되어 있는지 및 HTTP 날짜 또는 `x-amz-date` 헤더를 사용하는 요청 날짜도 포함되어 있는지 확인합니다.

IncompleteSignatureException 오류가 발생했고 서명의 구성이 올바른 경우 클라이언트측 요청에서 권한 부여 헤더의 SHA-256 해시 및 B64 인코딩을 계산하여 AWS 서비스로 전송되는 동안 인증 헤더가 수정되지 않았는지 확인할 수 있습니다.

1. 요청에서 전송한 [인증 헤더](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-authentication-methods.html)를 가져옵니다. 인증 헤더는 다음 예제와 유사합니다.

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

1. 인증 헤더의 SHA-256 해시를 계산합니다.

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

1. 해시된 인증 헤더를 Base64 형식으로 인코딩합니다.

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

1. 방금 계산한 해시 및 인코딩된 문자열을 오류 메시지로 받은 문자열과 비교합니다. 오류 메시지는 다음 예와 유사해야 합니다.

   ```
   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'.
   ```
+ 두 해시가 다른 경우 전송 중에 인증 헤더의 일부가 변경된 것입니다. 이는 네트워크 또는 클라이언트 핸들러가 서명된 헤더를 연결하거나 인증 헤더를 어떤 식으로든 변경했기 때문일 수 있습니다.
+ 두 해시가 일치하면 요청에서 보낸 인증 헤더가 AWS에서 받은 것과 일치합니다. 수신된 오류 메시지를 검토하여 문제가 잘못된 자격 증명이나 서명으로 인한 것인지 확인합니다. 이러한 오류는 이 페이지의 다른 섹션에서 다룹니다.

## 보안 인증 범위 오류
<a name="signature-v4-troubleshooting-credential-scope"></a>

[서명할 문자열 생성](reference_sigv-create-signed-request.md#create-string-to-sign)에서 생성한 보안 인증 범위는 서명을 특정 날짜, 리전 및 서비스로 제한합니다. 이 문자열의 형식은 다음과 같습니다.

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

**참고**  
SigV4a를 사용하는 경우 해당 리전은 보안 인증 범위에 포함되지 않습니다.

**날짜**  
보안 인증 범위에 x-amz-date 헤더와 동일한 날짜가 지정되어 있지 않은 경우, 서명 확인 단계가 실패하고 다음 오류 메시지가 표시됩니다.

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

요청에 미래의 시간이 지정되어 있는 경우, 서명 확인 단계가 실패하고 다음 오류 메시지가 표시됩니다.

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

요청이 만료된 경우, 서명 확인 단계가 실패하고 다음 오류 메시지가 표시됩니다.

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

**리전**  
보안 인증 범위가 요청과 동일한 리전을 지정하지 않는 경우, 서명 확인 단계가 실패하고 다음 오류 메시지가 표시됩니다.

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

**서비스**  
보안 인증 범위에 host 헤더와 동일한 서비스가 지정되어 있지 않은 경우, 서명 확인 단계가 실패하고 다음 오류 메시지가 표시됩니다.

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

**종료 문자열**  
보안 인증 범위가 aws4\$1request로 끝나지 않는 경우, 서명 확인 단계가 실패하고 다음 오류 메시지가 표시됩니다.

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

## 키 서명 오류
<a name="signature-v4-troubleshooting-key-signing"></a>

잘못된 서명 키 추출 또는 잘못된 암호화 사용으로 인해 발생하는 오류는 해결하는 데 어려움이 있습니다. 표준 문자열과 서명할 문자열이 올바른지 확인한 후, 다음 문제 중 하나를 확인할 수도 있습니다.
+ 비밀 액세스 키가 지정된 액세스 키 ID와 일치하지 않습니다.
+ 키 추출 코드에 문제가 있습니다.

비밀 키가 액세스 키 ID와 일치하는지 확인하려면, 정상적으로 작동하는 것으로 알려진 구현을 사용하여 비밀 키를 테스트합니다. 예를 들어 AWS SDK 또는 AWS CLI를 사용하여 AWS에 대한 요청을 보냅니다. 예제는 [서명 요청 예](reference_sigv-examples.md) 단원을 참조하십시오.