Hmac
AWS 簽名 v4 密鑰派生
使用 AWS 簽名 v4 生成授權標頭涉及派生簽名密鑰,如下所示:
https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html
static byte[] HmacSHA256(String data, byte[] key) throws Exception { String algorithm="HmacSHA256"; Mac mac = Mac.getInstance(algorithm); mac.init(new SecretKeySpec(key, algorithm)); return mac.doFinal(data.getBytes("UTF-8")); } static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception { byte[] kSecret = ("AWS4" + key).getBytes("UTF-8"); byte[] kDate = HmacSHA256(dateStamp, kSecret); byte[] kRegion = HmacSHA256(regionName, kDate); byte[] kService = HmacSHA256(serviceName, kRegion); byte[] kSigning = HmacSHA256("aws4_request", kService); return kSigning; }
- 如上所示,在多個後續步驟中計算 HMAC 有什麼好處,而不是只對串聯輸入(dateStamp、regionName 和 serviceName)進行一次 HmacSHA256 計算?
- 上述方法而不是使用標準 HKDF 有什麼好處?
交錯方案允許每個步驟由不同的實體執行。
- 中央伺服器儲存主密鑰,不與其他任何人通信。此中央伺服器應具有高可用性和高安全性,但吞吐量可能較低。密鑰可以儲存在硬體安全模組中。
- 第一步以明確的方式將密鑰與協議版本號結合起來(
"AWS4" + key
)。這允許協議升級使用相同的密鑰,因此您不必在協議升級的同時分發新密鑰。- 第二步將密鑰與日期結合起來(
HMAC(dateStamp, "AWS4" + key)
;協議指定了一個具有 1 天解析度的日期戳)。密鑰每天都在變化。更快的更改需要中央伺服器上的更多吞吐量,而較慢的更改意味著在鏈條下游的某些東西受到損害的情況下會產生更大的影響。- 每天,每個區域伺服器都會請求當天的區域密鑰
kRegion = HMAC(regionName, HMAC(dateStamp, "AWS4" + key))
。中央伺服器可以對區域伺服器進行身份驗證,以確保只有給定區域的伺服器才能獲得區域密鑰。kService = HMAC(kRegion, serviceName)
每個使用密鑰的服務都從它執行的區域請求自己的密鑰。區域伺服器可以對服務進行身份驗證,以確保服務不會學習另一個服務的密鑰。- 該服務將其密鑰與一個目的相結合:
kSigning = HMAC(kService, "aws4_request")
. 如果需要,這允許相同的主密鑰用於不同的目的。這種驚人的優勢是每個參與者只能訪問自己的密鑰。不可能找到給定的主密鑰
kRegion
,或者找到給定的區域密鑰kService
,或者找到給定的服務密鑰kSigning
。這最大限度地減少了妥協的影響:只有鏈下的參與者受到影響。例如,如果在 2022 年 1 月 5 日在美國數據中心發現漏洞,並且日誌顯示該漏洞發生在 2022 年 1 月 1 日,那麼只有在 2022 年 1 月 1 日之後在美國地區進行的簽名是可疑的,並且可能需要撤銷。在歐洲或 2022-01-01 之前製作的簽名仍然很好。當然,只有大型部署才會利用這種靈活性。在大多數應用程序中,整個計算是在同一個軟體中的單個函式中完成的。但該協議確實可以擴展到使用分區來減輕違規影響的大型部署。
一次合併所有輸入:
- 將具有大致相同的程式碼複雜性和執行時成本;
- 將具有稍高的分析複雜性(更難確保以獨特且完全可重複的方式組合輸入);
- 會不太靈活,不能做分區。