Azure Blob 授权 header | HMAC-SHA256 | OpenSSL、cURL 与 Java |签名不匹配

标签 azure azure-blob-storage

我一直在测试各种 Azure Blob Web 服务(列表、获取、放置、删除)的使用情况。我在 shell 脚本上使用 cURL 的测试成功了。但是,我尝试在 Java 上模仿此功能并不起作用。准确的说,Java生成的签名值与OpenSSL生成的签名值不匹配。

这是脚本,效果很好:

#!/bin/bash

# List the blobs in an Azure storage container.

echo "usage: ${0##*/} <storage-account-name> <container-name> <access-key>"

storage_account="ABC"
container_name="XYZ"
access_key="abc=="

blob_store_url="blob.core.windows.net"
authorization="SharedKey"

request_method="GET"
request_date=$(TZ=GMT date "+%a, %d %h %Y %H:%M:%S %Z")
storage_service_version="2015-02-21"

# HTTP Request headers
x_ms_date_h="x-ms-date:$request_date"
x_ms_version_h="x-ms-version:$storage_service_version"

# Build the signature string
canonicalized_headers="${x_ms_date_h}\n${x_ms_version_h}"
canonicalized_resource="/${storage_account}/${container_name}"

string_to_sign="${request_method}\n\n\n\n\n\n\n\n\n\n\n\n${canonicalized_headers}\n${canonicalized_resource}\ncomp:list\nrestype:container"

# Decode the Base64 encoded access key, convert to Hex.
decoded_hex_key="$(printf $access_key | base64 -d -w0 | xxd -p -c256)"

# Create the HMAC signature for the Authorization header
signature=$(printf "$string_to_sign" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$decoded_hex_key" -binary |  base64 -w0)

authorization_header="Authorization: $authorization $storage_account:$signature"
# -v or --trace to enable tracing
curl -v \
  -H "$x_ms_date_h" \
  -H "$x_ms_version_h" \
  -H "$authorization_header" \
  "https://${storage_account}.${blob_store_url}/${container_name}?restype=container&comp=list" -o Azure_ListBlob_Output.dat

这是 Java 函数,它生成的输出与前者的输出不匹配:

public static String computeHMac256(final String base64Key, final String stringToSign) {
         
//Signature=Base64(HMAC-SHA256(UTF8(StringToSign), Base64.decode(<your_azure_storage_account_shared_key>)))  

            try {
                
                byte[] key = Base64.getDecoder().decode(base64Key);
                Mac hmacSHA256 = Mac.getInstance("HmacSHA256");
                hmacSHA256.init(new SecretKeySpec(key, "HmacSHA256"));
                byte[] utf8Bytes = stringToSign.getBytes(StandardCharsets.UTF_8);
                byte[] output = hmacSHA256.doFinal(utf8Bytes);
                return Base64.getEncoder().encodeToString(output);              
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } 
            return null;
}

这是输入到 Java 函数的 stringToSign 值:

"GET\\n" + 
 "\\n" + 
 "\\n" + 
 "\\n" + 
 "\\n" + 
 "\\n" + 
 "\\n" + 
 "\\n" + 
 "\\n" + 
 "\\n" + 
 "\\n" + 
 "\\n" + 
 "x-ms-date:Tue, 30 Mar 2021 10:19:17 GMT\\n" + 
 "x-ms-version:2015-02-21\\n" + 
 "/ABC/XYZ\\n" + 
 "comp:list\\n" + 
 "restype:container";

当 Java 生成的签名传递给请求时,Azure 会报告以下内容:

HTTP/1.1 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

HERE抓取的java函数有什么问题吗? ?请帮忙。

最佳答案

更正变量stringToSign的以下值,解决了问题:

"GET\n" + 
 "\n" + 
 "\n" + 
 "\n" + 
 "\n" + 
 "\n" + 
 "\n" + 
 "\n" + 
 "\n" + 
 "\n" + 
 "\n" + 
 "\n" + 
 "x-ms-date:Tue, 30 Mar 2021 10:19:17 GMT\n" + 
 "x-ms-version:2015-02-21\n" + 
 "/ABC/XYZ\n" + 
 "comp:list\n" + 
 "restype:container

注意换行符从\\n 更改为\n。

现在,签名值匹配。感谢@GauravMantri 伸出援手。

关于Azure Blob 授权 header | HMAC-SHA256 | OpenSSL、cURL 与 Java |签名不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66871200/

相关文章:

azure - 从 Azure Blob 保存 X509 证书并在 Azure 网站中使用它

c# - 获取没有分区键的azure表中的所有实体

python - 如何使用 Azure Speech to Text 和 Python SDK 获取字级时间戳?

java - 使用服务帐户从azure blob存储中批量删除文件

asp.net - 在本地计算机上使用 Azure 存储模拟器时找不到上传的图像

azure - 将本地文件复制到 Azure Blob - 长文件名

azure - webjobs 使用 IBinder 删除 blob

python - Azure 认知文本分析工具返回 400 错误请求 Python

azure - 使用 Set-AzureRmResource - JSON Powershell 语法?

javascript - Azure:通过主体 ID 获取用户电子邮件