AWS Signature Version 4 (AWS4)
紀錄一下計算Signature的部分. 依序的步驟如下, 便可以計算出 signature.
1) canonical request
Canonical_Request =
url & query的部分是需要url encoded, 範例如下:
Canonical_URI:
encoded => /asustor-test/s3/upload/%E4%BA%BA
original => /asustor-test/s3/upload/人)
Canonical_Query_String:
encoded => delimiter=%2F&prefix=s3%2Fupload%2Ftest%2F
original => delimiter=/&prefix=s3/upload/test/)
- HTTP_Request_Method + '\n'
- Canonical_URI + '\n'
- Canonical_Query_String + '\n'
- Canonical_Headers + '\n'
- Signed_Headers + '\n'
- HexEncode(Hash(RequestPayload))
url & query的部分是需要url encoded, 範例如下:
Canonical_URI:
encoded => /asustor-test/s3/upload/%E4%BA%BA
original => /asustor-test/s3/upload/人)
Canonical_Query_String:
encoded => delimiter=%2F&prefix=s3%2Fupload%2Ftest%2F
original => delimiter=/&prefix=s3/upload/test/)
2) string to sign
StringToSign =
補充:
RequestDate為ISO8601 Basic format (YYYYMMDD'T'HHMMSS'Z')
- Algorithm + '\n'
- RequestDate + '\n'
- CredentialScope + '\n'
- Hashed(Canonical_Request))
補充:
RequestDate為ISO8601 Basic format (YYYYMMDD'T'HHMMSS'Z')
3) signing key
這邊主要是把secret access key 和 CredentialScope結合起來計算出signing key.
(e.g. Credential Scope為20110909/us-east-1/iam/aws4_request)
- kSecret = Your AWS Secret Access Key
- kDate = HMAC("AWS4" + kSecret, Date)
- kRegion = HMAC(kDate, Region)
- kService = HMAC(kRegion, Service)
- kSigning = HMAC(kService, "aws4_request")
4) signature
signature =
- HexEncode(HMAC( kSigning , StringToSign ))
Example
import hashlib import hmac def create_canonical_form(canonical_paras): canonical_form = canonical_paras['http_method'] + '\n' + canonical_paras['canonical_uri'] + '\n' + canonical_paras['canonical_query'] + '\n' + canonical_paras['canonical_headers'] + '\n' + canonical_paras['canonical_signed'] + '\n' + canonical_paras['hash_payload'] return canonical_form def stringtosign(algorithm, req_date, credential_scope, hash_canonical_form): stringtosignstr = algorithm + '\n' + req_date + '\n' + credential_scope + '\n' + hash_canonical_form return stringtosignstr def get_signing_key(secretkey, date, region, service, encryptedreq): ksecret = "AWS4%s" % (secretkey) kdate = hmac.new(ksecret.encode('utf-8'), date.encode('utf-8'), hashlib.sha256).digest() kregion = hmac.new(kdate, region.encode('utf-8'), hashlib.sha256).digest() kservice = hmac.new(kregion, service.encode('utf-8'), hashlib.sha256).digest() ksigning = hmac.new(kservice, encryptedreq.encode('utf-8'), hashlib.sha256).digest() return ksigning def test_case(): ''' <= canonical form => POST / content-type:application/x-www-form-urlencoded; charset=utf-8 host:iam.amazonaws.com x-amz-date:20110909T233600Z content-type;host;x-amz-date b6359072c78d70ebee1e81adcbab4f01bf2c23245fa365ef83fe8f1f955085e2 <= string to sign => AWS4-HMAC-SHA256 20110909T233600Z 20110909/us-east-1/iam/aws4_request 3511de7e95d28ecd39e9513b642aee07e54f4941150d8df8bf94b328ef7e55e2 <= signature => ced6826de92d2bdeed8f846f0bf508e8559e98e4b0199114b84c54174deb456c ''' hashpaylod = hashlib.new('sha256') hashpaylod.update(b"Action=ListUsers&Version=2010-05-08") paras = { "http_method":"POST" , "canonical_uri":"/" , "canonical_query":"" , "canonical_headers":"content-type:application/x-www-form-urlencoded; charset=utf-8\nhost:iam.amazonaws.com\nx-amz-date:20110909T233600Z\n" , "canonical_signed":"content-type;host;x-amz-date" , "hash_payload":(hashpaylod.hexdigest())} canonicalstr = create_canonical_form(paras) print("===canoncail form===\n{form}".format(form=canonicalstr)) hashcanonicalform = hashlib.new('sha256') hashcanonicalform.update(canonicalstr.encode('utf-8')) szstrtosign = stringtosign("AWS4-HMAC-SHA256", "20110909T233600Z", "20110909/us-east-1/iam/aws4_request", hashcanonicalform.hexdigest()) print("===string to sign===\n{strtosign}".format(strtosign=szstrtosign)) signingkey = get_signing_key("wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY", "20110909", "us-east-1", "iam", "aws4_request") signature = hmac.new(signingkey, (szstrtosign).encode('utf-8'), hashlib.sha256) print("===signature===\n{signature}".format(signature=signature.hexdigest())) if __name__ == '__main__': test_case()
留言
張貼留言