在某些情况下,需要确保Classic ASP生成的HMAC-SHA256哈希与PHP的hash_hmac('SHA256', $message, pack('H*', $secret))函数输出一致。然而,在尝试多种在线资源和方法后,发现结果并不匹配。
具体来说,当$message = 'stackoverflow' 和 $secret = '1234567890ABCDEF'时,期望的结果是:
bcb3452cd48c0f9048e64258ca24d0f3399563971d4a5dcdc531a7806b059e36
以下是几种尝试的方法及其结果:
方法1:使用CryptoJS库
通过dvim_brix_crypto-js-master_VB.asp脚本实现,但结果为:
c8375cf0c0db721ecc9c9b3a034284117d778ee8594285196c41d5020917f78c
方法2:纯Classic ASP实现
直接在Classic ASP中编写HMAC-SHA256函数,结果为:
bc0511316791176484c7d80bc8faaecd8388b75fb97516181ba6b361fd032531
方法3:使用Amazon AWS的sha256.wsc
通过WSC文件实现,结果与方法1相同:
c8375cf0c0db721ecc9c9b3a034284117d778ee8594285196c41d5020917f78c
问题似乎出在PHP中的pack()函数,它将十六进制字符串转换为二进制格式。为了在ASP中模拟这一过程,可以使用以下代码片段:
Dim key2, hexarr, binstr
key2 = "12 34 56 78 90 AB CD EF"
hexarr = Split(key2)
ReDim binarr(UBound(hexarr))
For i = 0 To UBound(hexarr)
binarr(i) = Chr(CInt("&h" & hexarr(i)))
Next
binstr = Join(binarr, "")
经过上述调整,所有方法现在都产生正确的结果:
8ab9e595eab259acb10aa18df7fdf0ecc5ec593f97572d3a4e09f05fdd3aeb8f
最终解决方案如下,利用Microsoft .NET Framework 2.0(从Windows Server 2003 R2开始预安装)提供的COM Interops功能:
'Returns Byte(), UTF-8 bytes of unicode string
Function Utf8Bytes(text)
With Server.CreateObject("System.Text.UTF8Encoding")
Utf8Bytes = .GetBytes_4(text)
End With
End Function
'Returns String, sequential hexadecimal digits per byte
data As Byte()
Function BinToHex(data)
With Server.CreateObject("MSXML2.DomDocument").CreateElement("b64")
.dataType = "bin.hex"
.nodeTypedValue = data
BinToHex = .text
End With
End Function
'Returns Byte(), a keyed hash generated using SHA256 method
data As String, key As Byte()
Function HashHmacSha256(data, key)
With Server.CreateObject("System.Security.Cryptography.HMACSHA256")
.Key = key
HashHmacSha256 = .ComputeHash_2(Utf8Bytes(data))
End With
End Function
'Returns Byte(), of a packed hexadecimal string
Instead of PHP's pack('H*'
Function HexToBin(data)
With Server.CreateObject("MSXML2.DomDocument").CreateElement("b64")
.dataType = "bin.hex"
.text = data
HexToBin = .nodeTypedValue
End With
End Function
packed_secret = HexToBin("1234567890ABCDEF")
message = "stackoverflow"
binary_hash = HashHmacSha256(message, packed_secret)
string_hash = BinToHex(binary_hash)
Response.Write string_hash
以上代码确保了在Classic ASP中生成的HMAC-SHA256哈希与PHP的结果完全一致。