VBA Excel HMACSHA256函数返回错误的摘要

时间:2017-05-20 23:14:27

标签: vba excel-vba excel

我希望在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在评论中链接的specpseudocode,我想出了以下代码,我将其添加到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

SHA256class 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。这样我就可以在整个过程中的各个步骤中与我的功能进行比较,以帮助追踪问题。

由于

〜一

0 个答案:

没有答案