중요
AWS SDK(샘플 코드 및 라이브러리
여러 서명 버전을 지원하는 리전에서는 수동 서명을 요청하는 경우 사용할 서명 버전을 지정해야 합니다. 다중 리전 액세스 포인트로 요청을 공급하는 경우 SDK와 CLI가 자동으로 추가 구성 없이 서명 버전 4A를 사용하는 것으로 전환됩니다.
AWS SigV4 서명 프로토콜을 사용하여 AWS API 요청에 대한 서명된 요청을 생성할 수 있습니다.
-
요청 세부 정보를 기반으로 표준 요청 생성.
-
AWS 자격 증명을 사용하여 서명 계산.
-
이 서명을 요청에 Authorization 헤더로 추가.
AWS에서는 이 프로세스를 복제하고 서명을 확인하여 그에 따라 액세스를 허용하거나 거부합니다.
AWS SigV4를 사용하여 API 요청에 서명하는 방법은 서명 요청 예 섹션을 참조하세요.
다음 표에서는 서명된 요청을 생성하는 과정에서 사용되는 함수를 설명합니다. 이러한 함수의 코드를 구현해야 합니다. 자세한 내용은 AWS SDK의 코드 예제를 참조하세요.
함수 | 설명 |
---|---|
|
문자열을 소문자로 변환합니다. |
|
소문자 16진법 인코딩. |
|
보안 해시 알고리즘(SHA) 암호화 해시 함수. |
|
제공된 서명 키를 포함한 SHA256 알고리즘을 사용하여 HMAC를 계산합니다. SigV4로 서명하는 경우 최종 서명입니다. |
|
퍼블릭-프라이빗 키 암호화를 기반으로 비대칭 서명을 사용해 계산된 타원 곡선 디지털 서명 알고리즘(ECDSA) 서명. |
|
NIST SP 800-108r1 |
|
ANSI X9.62에 설명된 대로, 옥텟 대 정수 함수. |
|
선행 또는 후행 공백을 모두 제거합니다. |
|
URI는 모든 바이트를 인코딩합니다. UriEncode()는 다음 규칙을 적용해야 합니다.
중요개발 플랫폼에서 제공하는 표준 UriEncode 함수는 구현상의 차이와 기본 RFC의 관련 모호성으로 인해 효과적이지 않을 수 있습니다. 인코딩이 제대로 작동하도록 사용자 지정 UriEncode 함수를 직접 작성하는 것이 좋습니다. Java에서 UriEncode 함수의 예를 보려면 GitHub 웹사이트에서 Java 유틸리티 |
참고
요청에 서명할 때 AWS SigV4 또는 AWS SigV4a를 사용할 수 있습니다. 둘 사이의 주요 차이점은 서명 계산 방법에 따라 결정됩니다. SigV4a를 사용하면 리전 세트가 서명할 문자열에 포함되지만 자격 증명 파생 단계의 일부는 아닙니다.
임시 보안 자격 증명을 사용하여 요청 서명
장기 보안 인증 정보를 사용하여 요청에 서명하는 대신 AWS Security Token Service(AWS STS)에서 제공하는 임시 보안 인증 정보를 사용할 수 있습니다.
임시 보안 자격 증명을 사용하는 경우 Authorization 헤더 또는 쿼리 문자열에 X-Amz-Security-Token
을 추가하거나 포함하여 세션 토큰을 저장해야 합니다. 일부 서비스의 경우 표준 요청에 X-Amz-Security-Token
을 추가해야 합니다. 다른 서비스의 경우, 서명을 계산한 후에 X-Amz-Security-Token
을 끝에 추가하기만 하면 됩니다. 구체적인 요구 사항은 각 AWS 서비스의 설명서를 참조하세요.
서명 단계 요약
표준 요청 생성
요청 내용(호스트, 작업, 헤더 등)을 표준 형식으로 정렬합니다. 표준 요청은 서명할 문자열을 생성하는 데 사용되는 입력 중 하나입니다. 표준 요청 생성에 대한 자세한 내용은 AWS API 요청 서명의 요소의 내용을 참조하세요.
표준 요청의 해시 생성
페이로드의 해시를 생성하는 데 사용한 것과 동일한 알고리즘을 사용하여 표준 요청을 해시합니다. 표준 요청의 해시는 소문자 16진수 문자의 문자열입니다.
서명할 문자열 생성
표준 요청과 추가 정보(예: 알고리즘, 요청 날짜, 자격 증명 범위, 표준 요청의 해시)를 사용하여 서명할 문자열을 생성합니다.
서명 키 추출
시크릿 액세스 키를 사용하여 요청에 서명하는 데 사용되는 키를 파생합니다.
서명 계산
파생된 서명 키를 해시 키로 사용하여 서명할 문자열에서 키가 추가된 해시 작업을 수행합니다.
요청에 서명 추가
HTTP 헤더 또는 요청의 쿼리 문자열에 계산된 서명을 추가합니다.
표준 요청 생성
표준 요청을 생성하려면 다음 문자열을 줄 바꿈 문자로 구분해 연결합니다. 이렇게 하면 사용자가 계산하는 서명이 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
리전에서 와일드카드(*)를 사용하여 여러 리전을 지정할 수 있습니다. 다음 예제에서 헤더는 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"))
표준 요청의 해시 생성
페이로드의 해시를 생성하는 데 사용한 것과 동일한 알고리즘을 사용하여 표준 요청의 해시(다이제스트)를 생성합니다. 표준 요청의 해시는 소문자 16진수 문자의 문자열입니다.
서명할 문자열 생성
서명할 문자열을 생성하려면 다음 문자열을 줄 바꿈 문자로 구분하여 연결합니다. 이 문자열을 줄 바꿈 문자로 끝내지 마세요.
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>
))
서명 키 추출
서명 키를 파생하려면 다음 프로세스 중 하나를 선택하여 SigV4 또는 SigV4a의 서명 키를 계산합니다.
SigV4에 대한 서명 키 파생
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 일반 참조의 리전 엔드포인트를 참조하세요.
-
Service
- 서비스 코드(예:ec2
)를 포함하는 문자열. -
이전 단계에서 생성한 서명할 문자열입니다.
SigV4에 대한 서명 키를 파생하는 방법
-
"AWS4"
와 비밀 액세스 키를 연결합니다. 연결된 문자열을 키로, 날짜 문자열을 데이터로 각각 사용하여 해시 함수를 호출합니다.DateKey = hash("AWS4" + Key, Date)
-
이전 호출의 결과를 키로, 리전 문자열을 데이터로 각각 사용하여 해시 함수를 호출합니다.
DateRegionKey = hash(kDate, Region)
-
이전 호출의 결과를 키로, 서비스 문자열을 데이터로 각각 사용하여 해시 함수를 호출합니다.
서비스 코드는 서비스에 의해 정의합니다. AWS Pricing CLI의 get-products
를 사용하여 서비스의 서비스 코드를 반환할 수 있습니다. DateRegionServiceKey = hash(kRegion, Service)
-
이전 호출의 결과를 키로, ‘aws4_request’를 데이터로 각각 사용하여 해시 함수를 호출합니다.
SigningKey = hash(kService, "aws4_request")
SigV4a에 대한 서명 키 파생
SigV4a에 대한 서명 키를 생성하려면 다음 프로세스를 사용하여 시크릿 액세스 키에서 키 페어를 파생합니다. 이 파생 구현의 예제는 C99 library implementation of AWS client-side authentication
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 }
서명 계산
서명 키를 파생한 후에는 요청에 추가할 서명을 계산합니다. 이 절차는 사용하는 서명 버전에 따라 달라집니다.
SigV4에 대한 서명을 계산하는 방법
-
이전 직접 호출의 결과를 키로, 서명할 문자열을 데이터로 각각 사용하여 해시 함수를 직접 호출하세요. 파생된 서명 키를 이 작업에 대한 해시 키로 사용합니다. 이진수 값 형식의 서명이 결과로 반환됩니다.
signature = hash(SigningKey,
string-to-sign
) -
서명을 이진수에서 소문자의 16진수 표현으로 변환합니다.
SigV4a에 대한 서명을 계산하는 방법
-
디지털 서명 알고리즘(ECDSA P-256)을 사용하여 이전 단계에서 생성한 서명할 문자열로 서명합니다. 이 서명에 사용되는 키는 위에서 설명한 시크릿 액세스 키에서 파생된 프라이빗 비대칭 키입니다.
signature = base16(
ECDSA-Sign
(k,string-to-sign
)) -
서명을 이진수에서 소문자의 16진수 표현으로 변환합니다.
요청에 서명 추가
계산된 서명을 요청에 추가합니다.
예: 인증 헤더
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
예: 쿼리 문자열에 인증 파라미터가 있는 요청
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