我希望在Excel VBA中实现HMACSHA256编码。
多个examples/answers使用System.Text.UTF8Encoding
& System.Security.Cryptography.HMACSHA256
但是我使用的是Windows 10 / Office 365,由于.NET 4.6框架(this post)导致自动化错误。
似乎确实存在existing VB6 implementation,但它使用了各种Windows库,我宁愿避免使用,因为我的代码可能需要在Office for Mac上运行。我也有兴趣将第一原则作为学习经验来实现。
Per mikegrann's comment on this page我决定在现有的SHA256 class module之上编写自己的HMAC包装器。
使用Mike在评论中链接的spec和pseudocode,我想出了以下代码,我将其添加到SHA256类模块中。
Public Function HMAC_SHA256(MessageString As String, KeyString As String) As String
Dim KeyByteArray() As Byte
Dim iKeyPadByteArray(63) As Byte, oKeyPadByteArray(63) As Byte
Dim iKeyPadString As String, oKeyPadString As String
Dim i As Long
'ensure key is same size as BLOCKSIZE (64)
If Len(KeyString) > BLOCKSIZE Then KeyString = SHA256 (KeyString) 'hash to reduce to 64 bytes
If Len(KeyString) < BLOCKSIZE Then KeyString = KeyString & _
String(BLOCKSIZE - Len(KeyString), &H0) 'add 0x00 padding
'convert key to byte array
KeyByteArray = StrConv(KeyString, vbFromUnicode)
'create iKeyPad & oKeyPad by Xor'ing with key
For i = 0 To 63
iKeyPadByteArray(i) = KeyByteArray(i) Xor &H36 'ipad is the byte 0x36 repeated 64 times
oKeyPadByteArray(i) = KeyByteArray(i) Xor &H5C 'opad is the byte 0x5c repeated 64 times
Next i
'convert back to string for use in SHA256 function
iKeyPadString = StrConv(iKeyPadByteArray, vbUnicode)
oKeyPadString = StrConv(oKeyPadByteArray, vbUnicode)
'generate hash
HMAC_SHA256 = SHA256(oKeyPadString & SHA256(iKeyPadString & MessageString))
End Function
SHA256
是class module
当我调用该函数时,它返回格式正确但不正确的HMACSHA256摘要。
Sub foo()
Dim SourceString As String, KeyVal As String
Dim foo As CSHA256
SourceString = "what do ya want for nothing?"
KeyVal = "Jefe"
Set foo = New CSHA256
Debug.Print "HMAC_SHA256: " & foo.HMAC_SHA256(SourceString, KeyVal)
Debug.Print "SHA256: " & foo.SHA256(SourceString)
End Sub
输出:
HMAC_SHA256: 1fa93aea23d7b353ef468e5ac460b2840c694842e7ac2018d58a7bf5b790b6e3
SHA256: b381e7fec653fc3ab9b178272366b8ac87fed8d31cb25ed1d0e1f3318644c89c
SHA256摘要是正确的,我已根据规范中的测试向量和在线生成器验证了它。但HMAC256摘要不正确,应该是......
5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843
我无法弄清楚HMAC包装器出了什么问题,因为没有太多事情发生。我认为可能是原因的两个方面是转换到/从字节数组转换到Xor'ing与iPad和&amp; OPAD。
我已经验证字节数组转换不包括尾随0
Screen Grab of Locals Window showing KeyByteArray
我还尝试将字节值转换为二进制并对它们应用位级XOR运算;然而,这导致与在字节数组上执行它相同的输出,所以我认为这不是问题。
任何帮助/建议我可能会出错我感激不尽。
========编辑========
在评论中与@ A.S.H交换后编辑帖子。
我一直在研究/试验字符串/字节转换,因为我同意这是错误所在的最可能的候选者。
Sub StringByteExperiments()
Dim KeyString As String, i As Long
Dim ByteArr_UTF8() As Byte, ByteArr_UTF16() As Byte
Dim ByteArr_UTF32() As Byte, ByteArr_ASC(3) As Byte
KeyString = "Jefe"
'=== String to Byte Array ===
ByteArr_UTF8 = StrConv(KeyString, vbFromUnicode)
'=> {74,101,102,101}
ByteArr_UTF16 = KeyString
'=> {74,0,101,0,102,0,101,0}
ByteArr_UTF32 = StrConv(KeyString, vbUnicode)
'=> {74,0,0,0,101,0,0,0,102,0,0,0,101,0,0,0}
For i = 1 To Len(KeyString)
ByteArr_ASC(i - 1) = AscW(Mid(KeyString, i, 1))
Next i
'=> {74,101,102,101}
'=== Byte Array to String ===
KeyString = StrConv(ByteArr_UTF8, vbUnicode)
'=> "Jefe"
KeyString = ByteArr_UT16
'=> doesn't compile
KeyString = Join(ByteArr_UTF16)
'=> err #5, invalid procedure call or argument
KeyString = StrConv(ByteArr_UTF16, vbFromUnicode)
'=> "??" can't parse
KeyString = StrConv(ByteArr_UTF16, vbUnicode)
'=> "J e f e "
KeyString = StrConv(ByteArr_UTF32, vbFromUnicode)
'=> "Jefe"
KeyString = StrConv(ByteArr_UTF32, vbUnicode)
'=> "J e f e "
KeyString = vbNullString
For i = LBound(ByteArr_ASC) To UBound(ByteArr_ASC)
KeyString = KeyString & Chr(ByteArr_ASC(i))
Next i
'=> "Jefe"
End Sub
@ A.S.H建议直接将字符串分配给字节数组,这样做会产生一个UTF16字节数组,即每个字符为2个字节。
这是否意味着VBA本地编码UTF16中的字符串? Len(KeyString)
返回4,而LenB(KeyString)
返回8,这表示每个字符有2个字节。
我已尝试解码为UTF16字节数组(即尾随零)并将其用于iPad&amp; oPad Xor操作然后转换回来,但它仍然导致不正确的摘要。
据我了解,HMAC_SHA256适用于UTF8字节数组,这似乎是我当前的函数正在做的事情,所以不知道错误是什么。
是否有人能够指出我可以为已知键值确定正确的UTF8字节数组的资源/方法以及正确的后Xor操作字节数组&amp; iPad和iPad的字符串值OPAD。这样我就可以在整个过程中的各个步骤中与我的功能进行比较,以帮助追踪问题。
由于
〜一