簽名應用及示例(V4版本)
更新時間 2024-09-26 15:34:32
最近更新時間: 2024-09-26 15:34:32
分享文章
介紹媒體存儲V4版本簽名應用及示例。
認證流程概述
V4簽名認證用于對請求進行安全驗證,確保請求在傳輸過程中未被篡改,并且確認請求來源合法。以下是實現 V4 簽名認證的詳細過程。
生成簽名步驟
提取基本元素
最終的請求鑒權頭 Authorization 頭中主要包含如下元素:
algorithm
Credential
SignedHeaders
Signature
algorithm元素與生成步驟
algorithm表示簽名的哈希算法,V4簽名通常取值是AWS4-HMAC-SHA256。格式如下:
algorithm="AWS4-HMAC-SHA256"
Credential元素與生成步驟
Credential 格式如下:
Credential={accessKey}/{credentialScope}
其中 credentialScope 格式如下:
credentialScope="{dateStamp}/{regionName}/{serviceName}/aws4_request"
SignedHeaders元素與生成步驟
SignedHeaders主要是由參與簽名的請求頭headerName按自然序排列并轉為小寫后用 ; 連接進行拼接而成,如:
signedHeaders="headerName1;headerName2;headerName3"
Signature
生成 stringToSign
Signature 的生成需要先生成 stringToSign,stringToSign的格式如下:
stringToSign="{algorithm}\n{requestDate}\n{credentialScope}\n{canonicalRequestHash}"
其中計算 canonicalRequestHash 需要先生成 canonicalRequest,其格式如下:
canonicalRequest="{httpMethod}\n{canonicalUri}\n{canonicalQueryString}\n{canonicalHeaders}\n{signedHeaders}\n{payloadHash}"
- httpMethod: 請求方法
- canonicalUri: 標準化的 URI,如:
/{bucketName}/{objectKey} - canonicalQueryString: 標準化的查詢字符串
- canonicalHeaders: 標準化的請求頭,如:
headerName1:headerValue1\nheaderName2:headerValue2\n - signedHeaders: 已簽名的請求頭列表
- payloadHash: 請求負載的 SHA256 哈希值(未簽名的負載使用 UNSIGNED-PAYLOAD)
得到canonicalRequest后,就可以計算canonicalRequestHash = HMAC-SHA256(canonicalRequest),并得到stringToSign
生成簽名密鑰
依次生成簽名密鑰,步驟如下:
kDate=HMAC-SHA256("AWS4"+{SecrectKey}, dateStamp)
kRegion=HMAC-SHA256(kDate, regionName)
kService=HMAC-SHA256(kRegion, serviceName)
kSigning=HMAC-SHA256(kService, "aws4_request")
得到簽名密鑰kSigning后,就可以計算得到Signature
signature=Hex(HMAC-SHA256(kSigning, stringToSign))
構造 Authorization Header
根據生成的簽名構造 Authorization Header:
Authorization: {algorithm} Credential={Credential}, SignedHeaders={SignedHeaders}, Signature={signature}
shell示例
以上傳對象為例:
#!/bin/sh
accessKey="訪問密鑰ID"
secretKey="私有訪問密鑰"
regionName="cn"
serviceName="s3"
# http or https
protocol="https"
host="gdoss.xstore.daliqc.cn"
bucketName="test-bucket"
objectKey="testobj"
sourceFile="/path/to/file"
httpMethod="PUT"
dateStamp=$(date -u +"%Y%m%d")
requestDate=$(date -u +"%Y%m%dT%H%M%SZ")
acl="public-read-write"
contentType="text/plain"
# Canonical Request
canonicalUri="/${bucketName}/${objectKey}"
canonicalQueryString=""
canonicalHeaders="content-type:${contentType}\nhost:${host}\nx-amz-acl:${acl}\nx-amz-date:${requestDate}\n"
signedHeaders="content-type;host;x-amz-acl;x-amz-date"
canonicalRequest="${httpMethod}\n${canonicalUri}\n${canonicalQueryString}\n${canonicalHeaders}\n${signedHeaders}\nUNSIGNED-PAYLOAD"
# Canonical Request Hash
canonicalRequestHash=$(echo -en "${canonicalRequest}" | iconv -t utf-8 | openssl dgst -sha256 | awk '{print $2}')
# String to Sign
algorithm="AWS4-HMAC-SHA256"
credentialScope="${dateStamp}/${regionName}/${serviceName}/aws4_request"
stringToSign="${algorithm}\n${requestDate}\n${credentialScope}\n${canonicalRequestHash}"
# 生成簽名密鑰
kDate=$(echo -en "${dateStamp}" | openssl dgst -sha256 -hmac "AWS4${secretKey}" -binary)
kRegion=$(echo -en "${regionName}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:$(echo -en "${kDate}" | xxd -p -c 256) -binary)
kService=$(echo -en "${serviceName}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:$(echo -en "${kRegion}" | xxd -p -c 256) -binary)
kSigning=$(echo -en "aws4_request" | openssl dgst -sha256 -mac HMAC -macopt hexkey:$(echo -en "${kService}" | xxd -p -c 256) -binary)
# 生成最終簽名
signature=$(echo -en "${stringToSign}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:$(echo -en "${kSigning}" | xxd -p -c 256) | awk '{print $2}')
# Authorization Header
authorizationHeader="${algorithm} Credential=${accessKey}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}"
curl -v -X ${httpMethod} \
-T "${sourceFile}" \
-H "Content-Type: ${contentType}" \
-H "x-amz-acl: ${acl}" \
-H "x-amz-date: ${requestDate}" \
-H "Authorization: ${authorizationHeader}" \
"${protocol}://${host}/${bucketName}/${objectKey}"