经典 ASP 中的各种 HMAC_SHA256 函数给出不同的结果

问题描述 投票:0回答:2

不知何故,我需要在经典 ASP 中生成一个哈希值,这相当于 PHP 的以下函数的输出:

$hash = hash_hmac('SHA256', $message, pack('H*', $secret));

哪里

$message = 'stackoverflow'; $secret = '1234567890ABCDEF';
。我在网上尝试了很多方法,但没有一个与 PHP 结果匹配:

bcb3452cd48c0f9048e64258ca24d0f3399563971d4a5dcdc531a7806b059e36

方法一:在线使用dvim_brix_crypto-js-master_VB.asp(使用CrytoJS)

Function mac256(ent, key) 
    Dim encWA
    Set encWA = ConvertUtf8StrToWordArray(ent)
    Dim keyWA
    Set keyWA = ConvertUtf8StrToWordArray(key)
    Dim resWA
    Set resWA = CryptoJS.HmacSHA256(encWA, key)
    Set mac256 = resWA
End Function

Function ConvertUtf8StrToWordArray(data)
    If (typename(data) = "String") Then
        Set ConvertUtf8StrToWordArray = CryptoJS.enc.Utf8.parse(data)
    Elseif (typename(data) = "JScriptTypeInfo") Then
        On error resume next
        'Set ConvertUtf8StrToWordArray = CryptoJS.enc.Utf8.parse(data.toString(CryptoJS.enc.Utf8)) 
        Set ConvertUtf8StrToWordArray = CryptoJS.lib.WordArray.create().concat(data) 'Just assert that data is WordArray
        If Err.number>0 Then
            Set ConvertUtf8StrToWordArray = Nothing
        End if
        On error goto 0
    Else
        Set ConvertUtf8StrToWordArray = Nothing
    End if
End Function

该脚本可以在here找到。该方法给出:

c8375cf0c0db721ecc9c9b3a034284117d778ee8594285196c41d5020917f78c

方法2:纯经典ASP方法

Public Function HMAC_SHA256(prmKey, prmData)
    Dim theKey : theKey = prmKey
    Dim Block_Size, O_Pad, I_Pad
    Block_Size = 64
    O_Pad = 92 'HEX: 5c'
    I_Pad = 54 'HEX: 36'

    Dim iter, iter2
    If Len(theKey) < Block_Size Then
        For iter = 1 to Block_Size - Len(theKey)
            theKey = theKey & chr(0)
        Next
    ElseIf Len(theKey) > Block_Size Then
        theKey = SHA256(theKey)
    End If

    Dim o_key_pad : o_key_pad = ""
    Dim i_key_pad : i_key_pad = ""
    For iter = 1 to Block_Size
        o_key_pad = o_key_pad & Chr(Asc(Mid(theKey,iter,1)) xor O_Pad)
        i_key_pad = i_key_pad & Chr(Asc(Mid(theKey,iter,1)) xor I_Pad)
    Next

    HMAC_SHA256 = SHA256(o_key_pad & SHA256(i_key_pad & prmData))
End Function
result = HMAC_SHA256(secret, message)

此方法给出:

bc0511316791176484c7d80bc8faaecd8388b75fb97516181ba6b361fd032531

方法3:使用亚马逊AWS的sha256.wsc(使用CrytoJS)

Dim sha
Set sha = GetObject( "script:" & Server.MapPath("sha256.wsc") )
sha.hexcase = 0
result = sha.b64_hmac_sha256(secret, message)

WSC 可以在这里找到。此方法给出(与方法 1 相同的结果):

c8375cf0c0db721ecc9c9b3a034284117d778ee8594285196c41d5020917f78c

我认为问题在于

pack()
部分,它将十六进制字符串更改为二进制。因此,我找到了在ASP中重现
pack()
功能的方法:

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, "")

其中

key2
是原始秘密,每 2 个字符添加空格。通过将
secret
替换为
binstr
,这些方法现在可以生成:

Method 1: 8ab9e595eab259acb10aa18df7fdf0ecc5ec593f97572d3a4e09f05fdd3aeb8f
Method 2: d23fcafb41d7b581fdae8c2a4a65bc3b19276a4bd367eda9e8e3de43b6a4d355
Method 3: 8ab9e595eab259acb10aa18df7fdf0ecc5ec593f97572d3a4e09f05fdd3aeb8f

以上结果均与 PHP 的结果不同。我现在错过了什么?

php asp-classic cryptojs
2个回答
5
投票

查看以下示例。

此方法的唯一要求是 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

0
投票

谢谢@Kul-Tigin 提供的出色解决方案,但我认为您犯了一个小小的错误。 HMACSHA256 对象的 Key 参数应该是您自己的 Utf8Bytes() 函数的返回值。不是您指定的 HexToBin() 。解决这个问题后,我可以使用 PHP 的 hash_hmac() 函数成功验证这项工作的结果。

对于那些感兴趣的人,这里是单个经典 ASP 函数中代码的简化版本:

Function hash_hmac(Dat, Key) ' Same as PHP hash_hmac("sha256", Dat, Key, true)
    Dim objText, objCrypt, objBinHex
    Set objText = Server.CreateObject("System.Text.UTF8Encoding")
        Set objBinHex = Server.CreateObject("MSXML2.DomDocument").CreateElement("b64")
            objBinHex.dataType = "bin.hex"
            Set objCrypt = Server.CreateObject("System.Security.Cryptography.HMACSHA256")
                objCrypt.Key = objText.GetBytes_4(Key)
                objBinHex.nodeTypedValue = objCrypt.ComputeHash_2(objText.GetBytes_4(Dat))
                HashHMAC = objBinHex.Text
            Set objCrypt = Nothing
        Set objBinHex = Nothing
    Set objText = Nothing
End Function
© www.soinside.com 2019 - 2024. All rights reserved.