为AWIS创建AWS v4签名 [英] Creating a AWS v4 Signature for AWIS
问题描述
多年来,我们一直在使用AWS v2签名,现在已被v4取代.
For years we've been using the AWS v2 signature which is now replaced by v4.
我正在慢慢地完成所有步骤,但是在步骤3上一直没有解决,它要求以二进制格式输出的HMAC-SHA256加密. https://docs.aws.amazon.com/AlexaWebInfoService/latest/CalculatingSignatures. html https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
I'm slowly working through all the steps but have come unstuck on step 3 where it's asking for HMAC-SHA256 encryptions that output in binary format. https://docs.aws.amazon.com/AlexaWebInfoService/latest/CalculatingSignatures.html https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
我需要在经典ASP 中执行此操作,我有对SHA256进行编码的脚本,但是找不到能以二进制输出的脚本.
I need to do this in Classic ASP, I have scripts that encode SHA256 but nothing I can find that will output in binary.
我最接近的是Chilkat组件,该组件似乎从SHA256哈希输出二进制文件,但是我不知道如何实现这一点: http://www.chilkatsoft.com/refdoc/xChilkatCrypt2Ref.html#method72
The nearest I've got is the Chilkat component that seems to output binary from SHA256 hashes but I can't work out how to achieve this: http://www.chilkatsoft.com/refdoc/xChilkatCrypt2Ref.html#method72
有人可以通过脚本(asp,vbscript,javascript)或Chilkat(或其他)组件为我指明正确的方向吗?真正引起问题的是二进制输出.
Can anyone point me in the right direction either with script (asp, vbscript, javascript) or with the Chilkat (or other) component? It's the binary output that is really causing problems.
非常感谢
推荐答案
AWS V4签名生成过程让我抓狂了好几天(也是HMAC二进制输出也让我很头疼),但是可以使用pure经典ASP.这是我编写的用于生成签名的S3 URL的类(我不熟悉AWIS,但是在浏览了您链接的文档后,我可以看到签名生成过程是相同的):
The AWS V4 Signature generation process had me scratching my head for days (it was the HMAC binary output that had me stumped too), but it is possible using pure classic ASP. Here's a class I wrote for generating signed S3 URLs (I'm not familiar with AWIS, but after glancing at the documentation you linked I can see the signature generation process is the same):
Class AmazonWebServices
Private AWS_utc, AWS_timestamp, AWS_timestamp_short, AWS_url, AWS_headers, AWS_string_to_sign, AWS_signature
Private AWS_S3_key, AWS_S3_region, AWS_S3_version, AWS_S3_bucket, AWS_S3_host, AWS_S3_secret
Private Sub Class_Initialize()
' AWS expects a UTC timestamp, if your server isn't set to UTC you will need to apply
' an offset to NOW() using DateAdd()
AWS_utc = NOW() ' Or to apply an offset: DateAdd("h",-1,NOW())
AWS_timestamp = year(AWS_utc) & zero_pad(month(AWS_utc)) & zero_pad(day(AWS_utc)) &_
"T" & zero_pad(hour(AWS_utc)) & zero_pad(minute(AWS_utc)) & zero_pad(second(AWS_utc)) & "Z"
AWS_timestamp_short = left(AWS_timestamp,8)
AWS_S3_key = "XXXXXXXXXXXXXXXXXXXX"
AWS_S3_region = "eu-west-2"
AWS_S3_version = "2006-03-01"
AWS_S3_bucket = "BUCKETNAME"
AWS_S3_host = AWS_S3_bucket & ".s3." & AWS_S3_region & ".amazonaws.com"
AWS_S3_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
End Sub
public function s3_signed_url(ByVal theFile, ByVal expire)
' expire is the number of seconds to keep the url alive
' Prefix the file name with a slash
if NOT inStr(theFile,"/") = 1 then theFile = "/" & theFile
' Construct the S3 URL
AWS_url = "https://" & AWS_S3_host & theFile &_
"?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD" &_
"&X-Amz-Algorithm=AWS4-HMAC-SHA256" &_
"&X-Amz-Credential=" & AWS_S3_key &_
"%2F" & AWS_timestamp_short &_
"%2F" & AWS_S3_region &_
"%2Fs3" &_
"%2Faws4_request" &_
"&X-Amz-Date=" & AWS_timestamp &_
"&X-Amz-SignedHeaders=host" &_
"&X-Amz-Expires=" & expire &_
"&X-Amz-Signature="
' Construct the GET headers
' headers need to be separated with just a line feed
' VBlf = line feed
' VBcr = carriage return
' VBcrlf = carriage return & line feed
' Anything but VBlf (or chr(10)) will return a signature mismatch
AWS_headers = "GET" & VBlf &_
theFile & VBlf &_
"X-Amz-Algorithm=AWS4-HMAC-SHA256" &_
"&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD" &_
"&X-Amz-Credential=" & AWS_S3_key &_
"%2F" & AWS_timestamp_short &_
"%2F" & AWS_S3_region &_
"%2Fs3" &_
"%2Faws4_request" &_
"&X-Amz-Date=" & AWS_timestamp &_
"&X-Amz-Expires=" & expire &_
"&X-Amz-SignedHeaders=host" & VBlf &_
"host:" & AWS_S3_host & VBlf & VBlf &_
"host" & VBlf &_
"UNSIGNED-PAYLOAD"
' GET headers are hashed with SHA256
AWS_headers = hash(AWS_headers,"SHA256","hex")
' Construct the string to sign
AWS_string_to_sign = "AWS4-HMAC-SHA256" & VBlf &_
AWS_timestamp & VBlf &_
AWS_timestamp_short & "/" & AWS_S3_region & "/s3/aws4_request" & VBlf &_
AWS_headers
' date key, generated by hashing the short timestamp using the secret key as the HMAC key
AWS_signature = hash_hmac("AWS4" & AWS_S3_secret,AWS_timestamp_short,"SHA256","raw")
' region key, generated by hashing the region using the date key as the HMAC key
AWS_signature = hash_hmac(AWS_signature,AWS_S3_region,"SHA256","raw")
' service key, generated by hashing the service name using the region key as the HMAC key
AWS_signature = hash_hmac(AWS_signature,"s3","SHA256","raw")
' signing key, generated by hashing the request type using the service key as the HMAC key
AWS_signature = hash_hmac(AWS_signature,"aws4_request","SHA256","raw")
' signature, generated by hashing the "string to sign" using the signing key as the HMAC key
AWS_signature = hash_hmac(AWS_signature,AWS_string_to_sign,"SHA256","hex")
' Return the complete URL with signature
s3_signed_url = AWS_url & AWS_signature
end function
private function hash(ByVal input, ByVal alg, ByVal encoding)
' Convert the input to bytes if not already
if NOT vartype(input) = 8209 then input = string_to_UTF8_bytes(input)
Dim hAlg : Set hAlg = Server.CreateObject("System.Security.Cryptography." & get_hash_class(alg))
hash = binary_encode(hAlg.ComputeHash_2((input)),encoding)
set hAlg = nothing
end function
private function hash_hmac(ByVal secret, ByVal message, ByVal alg, ByVal encoding)
' Convert the input to bytes if not already
if NOT vartype(secret) = 8209 then secret = string_to_UTF8_bytes(secret)
if NOT vartype(message) = 8209 then message = string_to_UTF8_bytes(message)
Dim hAlg : Set hAlg = Server.CreateObject("System.Security.Cryptography." & get_hmac_class(alg))
hAlg.Initialize()
hAlg.key = secret
hash_hmac = binary_encode(hAlg.ComputeHash_2((message)),encoding)
set hAlg = nothing
end function
private function binary_encode(ByVal binary, ByVal encoding)
encoding = lCase(encoding)
if encoding = "raw" then
binary_encode = binary
exit function
end if
Dim enc : Set enc = Server.CreateObject("MSXML2.DomDocument").CreateElement("encode")
if encoding = "base64" OR encoding = "b64" then
' base64 string
enc.dataType = "bin.base64"
enc.nodeTypedValue = binary
binary_encode = enc.Text
else
' hexadecimal string
enc.dataType = "bin.hex"
enc.nodeTypedValue = binary
binary_encode = enc.Text
end if
Set enc = nothing
end function
private function get_hash_class(ByVal alg)
' get the cryptography class name for the specified hashing algorithm,
' return the class name for SHA1 if not found
select case uCase(alg)
case "MD5"
get_hash_class = "MD5CryptoServiceProvider"
case "SHA1"
get_hash_class = "SHA1CryptoServiceProvider"
case "SHA2","SHA256"
get_hash_class = "SHA256Managed"
case "SHA3","SHA384"
get_hash_class = "SHA384Managed"
case "SHA5","SHA512"
get_hash_class = "SHA512Managed"
case else
get_hash_class = "SHA1CryptoServiceProvider"
end select
end function
private function get_hmac_class(ByVal alg)
' get the cryptography class name for the specified HMAC algorithm,
' return the class name for SHA1 if not found
select case uCase(alg)
case "MD5"
get_hmac_class = "HMACMD5"
case "SHA1"
get_hmac_class = "HMACSHA1"
case "SHA3","SHA384"
get_hmac_class = "HMACSHA384"
case "SHA2","SHA256"
get_hmac_class = "HMACSHA256"
case "SHA5","SHA512"
get_hmac_class = "HMACSHA512"
case else
get_hmac_class = "HMACSHA1"
end select
end function
private function string_to_UTF8_bytes(ByVal aString)
' convert a UTF8 string to bytes
Dim UTF8 : Set UTF8 = Server.CreateObject("System.Text.UTF8Encoding")
string_to_UTF8_bytes = UTF8.GetBytes_4(aString)
set UTF8 = nothing
end function
private function zero_pad(ByVal theNum)
if len(theNum) = 1 then
zero_pad = cStr("0" & theNum)
else
zero_pad = theNum
end if
end function
end class
要生成24小时S3签名的URL,请执行以下操作:
To generate a 24 hour S3 signed URL:
set AWS = new AmazonWebServices
response.write AWS.s3_signed_url("file.name",86400)
set AWS = nothing
示例输出:
https://BUCKETNAME.s3.eu-west-2.amazonaws.com/file.name?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXXXXXXXXXXXXXXXXX%2F20190404%2Feu-west-2%2Fs3%2Faws4_request&X-Amz-Date=20190404T130643Z&X-Amz-SignedHeaders=host&X-Amz-Expires=86400&X-Amz-Signature=4e1ef2a12c304de0896f5faa2a472be5f66724d3c9778a73a1d623d30769c162
Time to execute: 0.00391s
您在问题中也提到了奇尔卡特. Chilkat实际上可以为您生成v4签名:
You also mentioned Chilkat in your question. Chilkat can actually generate v4 signatures for you:
https://www.chilkatsoft.com/refdoc/xChilkatAuthAwsRef.html
https://www.example-code.com/asp/aws_pre_signed_url_v4.asp
它确实需要许可证.我几年前买了一个,我强烈推荐给仍然使用Classic ASP的任何人.
It does require a license though. I bought one a few years back and I'd highly recommend it for anyone who still uses Classic ASP.
这篇关于为AWIS创建AWS v4签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!