asp-classic - 经典 ASP VBScript 中的 HMAC 算法 (SHA256)

标签 asp-classic hmac

我正在尝试使用 SHA256 作为哈希在经典 ASP 中编写 HMAC 函数。我认为我做对了,但结果与 Wikipedia page 上列出的示例不同。 。我见过几个人们通过包含 WSC 在经典 ASP 中使用 HMAC SHA256 的示例。这不是我想做的。

这是函数:

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

这是来自 Wikipedia 的 HMAC 的伪代码:

function hmac (key, message)
    if (length(key) > blocksize) then
        key = hash(key) // keys longer than blocksize are shortened
    end if
    if (length(key) < blocksize) then
        key = key ∥ [0x00 * (blocksize - length(key))] // keys shorter than blocksize are zero-padded (where ∥ is concatenation)
    end if

    o_key_pad = [0x5c * blocksize] ⊕ key // Where blocksize is that of the underlying hash function
    i_key_pad = [0x36 * blocksize] ⊕ key // Where ⊕ is exclusive or (XOR)

    return hash(o_key_pad ∥ hash(i_key_pad ∥ message)) // Where ∥ is concatenation
end function

我一生都无法确定这里出了什么问题。我想有人会告诉我这在 ASP 中是不可能的,这就是为什么有这么多建议使用 WSC。如果是这样,有人可以解释为什么这是不可能的吗?我没有看到任何事情会使这成为不可能。

谢谢!

编辑:我已经确保我使用的 SHA256 函数给出了正确的哈希值,因此与此无关。我还尝试过对 SHA256 函数的结果进行 UCase 处理,但没有结果。

EDIT2:从 wiki 页面添加示例。

最佳答案

嗯,我曾经在经典 ASP 中实现了 TEA(微型加密算法)并遇到了类似的问题。就我而言,根本原因是 ASP 将您连接的字符串 (& char) 再次保存为 UTF-16,因此偏移量并不总是与我期望的位置匹配。

我不知道这是否适用于您的用例,因为我必须使用 UTF-8 特殊字符。

我的解决方案是使用一组长整型数组,我可以使用我的二进制函数正确定位它。以下是使用该数组的函数,希望对您有所帮助。

    '*******************************************************************************
    ' getArrayFromInputString (FUNCTION)
    '
    ' PARAMETERS:
    ' (In) - s_source - Source string (format is defined by n_options)
    ' (In) - n_blocksize - Blocksize, which is corrected by padding
    ' (In) - n_options - Options using follobing bits:
    '        1: string is in HEX format (e.g. DFD14DAFD9C555C07FEB8F3DA90DEA27)

    ' RETURN VALUE:
    ' long array
    '
    ' DESCRIPTION:
    ' allows to import strings in various formats for all input functions
    '*******************************************************************************
    private function getArrayFromInputString(s_source, n_blocksize, n_options)
        ' n_options:

        dim a_out, s_padded_string

        if (n_options AND 1) = 1 then
            s_padded_string = padString(s_source, n_blocksize * 2, "0")
            a_out = convertHexStringToArray(s_padded_string)
        else
            if b_unicode_ then
                s_padded_string = padString(s_source, int(n_blocksize / 2), " ")
                a_out = convertStringToArray_Unicode(s_padded_string)
            else    
                s_padded_string = padString(s_source, n_blocksize, " ")
                a_out = convertStringToArray(s_padded_string)
            end if
        end if

        getArrayFromInputString = a_out
    end function


    '*******************************************************************************
    ' convertStringToArray (FUNCTION)
    '
    ' PARAMETERS:
    ' (In) - s_source - Source string to build the array from
    '                   length MUST be in multiples of 4!
    '
    ' RETURN VALUE:
    ' Array of type Long - Length is 4 times smaller than the string length
    '
    ' DESCRIPTION:
    ' Blocks of four characters are calculated into one Long entry of the result array
    '*******************************************************************************
    private function convertStringToArray(s_source) ' returns long array
        dim a_out, n_index, n_length, n_temp
        dim n_array_index, n_nibble

        n_length = len(s_source)
        redim a_out(int(n_length / 4))

        for n_index=0 to n_length - 1
            n_temp = asc(mid(s_source, n_index + 1, 1))
            n_array_index = int(n_index / 4)
            n_nibble = n_index MOD 4

            a_out(n_array_index) = AddUnsigned(a_out(n_array_index), LShift(n_temp, (3 - n_nibble) * 8))
        next
        convertStringToArray = a_out
    end function

    '*******************************************************************************
    ' convertHexStringToArray (unicode version)
    private function convertStringToArray_Unicode(s_source) ' returns long array
        dim a_out, n_index, n_length, n_temp
        dim n_array_index, n_nibble

        n_length = len(s_source)
        redim a_out(int(n_length / 2))

        for n_index=0 to n_length - 1
            n_temp = ascw(mid(s_source, n_index + 1, 1))

            n_array_index = int(n_index / 2)
            n_nibble = (n_index MOD 2)

            a_out(n_array_index) = AddUnsigned(a_out(n_array_index), LShift(n_temp, (1 - n_nibble) * 16))
        next
        convertStringToArray_Unicode = a_out
    end function

    '*******************************************************************************
    ' convertHexStringToArray (FUNCTION)
    '
    ' PARAMETERS:
    ' (In) - s_source - Source string in hex format, e.g. "EFCE016503CDDB53"
    '                   length MUST be in multiples of 8!
    '
    ' RETURN VALUE:
    ' Array of type Long - Length is 8 times smaller than the string length
    '
    ' DESCRIPTION:
    ' Blocks of eight characters are calculated into one Long entry of the result array
    '*******************************************************************************
    private function convertHexStringToArray(s_source) ' returns long array
        dim a_out, n_index, n_length, n_temp
        dim n_array_index, n_nibble

        n_length = len(s_source)
        redim a_out(int(n_length / 8))

        for n_index=0 to n_length - 1 step 2
            n_temp = CInt("&H" & mid(s_source, n_index + 1, 2))
            n_array_index = int(n_index / 8)
            n_nibble = int((n_index MOD 8) / 2)

            a_out(n_array_index) = AddUnsigned(a_out(n_array_index), LShift(n_temp, (3 - n_nibble) * 8))
        next
        convertHexStringToArray = a_out
    end function


    '*******************************************************************************
    ' padString (FUNCTION)
    '
    ' PARAMETERS:
    ' (In) - s_source
    ' (In) - n_blocksize
    ' (In) - s_padding_char
    '
    ' RETURN VALUE:
    ' String - padded source string
    '
    ' DESCRIPTION:
    ' ensure, that the plaintext is multiples of n_blocksize bytes long, the needed amount of s_padding_char is applied
    '*******************************************************************************
    private function padString(s_source, n_blocksize, s_padding_char)
        dim s_out, n_length, n_padding, n_index

        s_out = s_source
        n_length = len(s_source)
        if n_length MOD n_blocksize>0 then
            n_padding = n_blocksize - n_length MOD n_blocksize
            for n_index=1 to n_padding
                s_out = s_out & left(s_padding_char, 1)
            next
        end if

        padString = s_out
    end function

    '*******************************************************************************
    ' printArray (FUNCTION)
    '
    ' PARAMETERS:
    ' (In) - s_prefix - just a string to be written in front for distinction of multiple arrays
    ' (In) - a_data - long array to print out
    '
    ' RETURN VALUE:
    ' none
    '
    ' DESCRIPTION:
    ' debug output function
    '*******************************************************************************
    private function printArray(s_prefix, a_data)
        dim n_index
        for n_index=0 to UBound(a_data) - 1
            Response.Write "<p>" & s_prefix & a_data(n_index) & " - " & getHex(a_data(n_index)) & "</p>" & vbNewline
        next
    end function

    '*******************************************************************************
    ' Some more little helper functions
    '*******************************************************************************
    private function getHex(n_value)
        getHex = Right("00000000" & Hex(n_value), 8)
    end function

    private function getStringFromLong(n_value)
        getStringFromLong = _
            Chr(RShift(n_value, 24) AND &HFF) & _
            Chr(RShift(n_value, 16) AND &HFF) & _
            Chr(RShift(n_value, 8) AND &HFF) & _
            Chr(n_value AND &HFF)
    end function

    private function getStringFromLong_Unicode(n_value)
        dim s_temp

        s_temp = getHex(n_value)
        getStringFromLong_Unicode = _
            ChrW(int("&H" & mid(s_temp, 1, 4))) & _
            ChrW(int("&H" & mid(s_temp, 5, 4)))
    end function

关于asp-classic - 经典 ASP VBScript 中的 HMAC 算法 (SHA256),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32029595/

相关文章:

xml - 如何在经典 ASP 中使用地理编码 API v3

asp-classic - 如何在经典 ASP 中遍历集合?

sql-server - 从经典 ASP 连接时 SQL Server 中的应用程序名称

使用 HMAC+nonce 存储 PHP 密码 - nonce 随机性重要吗?

http - 计算HMACs时如何确定HTTP请求参数顺序?

asp-classic - 经典的asp Format Number显示一个特殊字符(Â)作为千位分隔符

asp-classic - 使用 JavaScript 类 ASP - 处理缺少 Request.QueryString 中的查询参数的情况

java - 无法解决 HTTP 基本身份验证问题 - 消息 header 中存在非法字符(由 HMAC 编码产生)

ios - 如何在 HMAC 中以 HEX Swift iOS 形式传递 key

php - hmac哈希在PHP和Go中不一样