经典 ASP VBScript 中的 HMAC 算法 (SHA256) [英] HMAC Algorithm (SHA256) in Classic ASP VBScript
问题描述
我正在尝试使用 SHA256 作为哈希值在 Classic ASP 中编写 HMAC 函数.我以为我做对了,但是 维基百科上列出的示例的结果并不相同页.我已经看到了几个在经典 ASP 中通过包含 WSC 使用 HMAC SHA256 的示例.这不是我想做的.
I'm trying to write an HMAC function in Classic ASP using SHA256 as the hash. I thought I got it right, but the results aren't the same for the examples listed on the Wikipedia page. I've seen several examples of people using HMAC SHA256 in Classic ASP by including a WSC. This is not what I want to do.
函数如下:
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
这是来自维基百科的 HMAC 的伪代码:
And here's the pseudocode from Wikipedia's 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 的建议.如果是这种情况,有人可以解释为什么这是不可能的吗?我看不出有什么能让这成为不可能的事情.
I can't for the life of me determine what's wrong here. I imagine someone's going to tell me it's impossible in ASP and that's why there are so many suggestions to use the WSC. If this is the case, can someone explain why it's impossible? I don't see anything that should make this impossible.
谢谢!
我已经确定我使用的 SHA256 函数给出了正确的哈希值,所以这与此无关.我也试过 UCase'ing SHA256 函数的结果,没有骰子.
I've made sure the SHA256 function I use is giving the correct hashes, so it's nothing to do with that. I've also tried UCase'ing the results of the SHA256 function, and no dice.
从 wiki 页面添加示例.
Added example from wiki page.
推荐答案
嗯,我曾经在经典的 ASP 中实现过 TEA(微型加密算法),也遇到过类似的问题.就我而言,根本原因是 ASP 将您要连接的字符串 (& char) 再次保存为 UTF-16,因此偏移量并不总是与我预期的匹配.
Well, I once implemented TEA (tiny encryption algorithm) in classic ASP and had similar problems. In my case, the root cause was, that ASP saves the strings you are concatenating (& char) again as UTF-16 and so the offsets did not always match up where I expected them.
我不知道这是否适用于您的用例,因为我必须使用 UTF-8 特殊字符.
I don't know if this applies to your use case, since I had to work with UTF-8 special characters.
我的解决方案是使用一个 long 数组,我可以使用我的二进制函数正确定位.以下是使用此数组的函数,希望它们对您有所帮助.
My solution was to work with an array of longs, that I could target properly with my binary functions. Here are the functions to work with this array, hoping they are helpful for you.
'*******************************************************************************
' 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 VBScript 中的 HMAC 算法 (SHA256)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!