VBA中的HMAC-SHA1 URL加密会产生错误的输出

时间:2014-02-26 11:54:53

标签: python .net vba encryption hmacsha1

对于Google Maps Business API查询,我需要使用HMAC-SHA1对每个查询进行数字签名。我们使用带有VBA宏的Excel文件来发送查询并解析输出,因此我想在VBA中创建签名。我发现了这个问题+答案:Base64 HMAC SHA1 String in VBA
但是,当查询发送到Google API时,此代码的字符串签名无效。

Google提供了一些示例脚本。我使用与上面测试VBA代码相同的输入测试Python sample script,并且Python代码做了返回有效签名。所以似乎提供的VBA代码没有构造一个正确的HMAC-SHA1签名,但我找不到问题(我没有加密经验,只有基本的VBA知识)。

我为测试目的创建了一个HMAC-SHA1密钥:1412SxPev45oMMRQSXazwQp789yM=
当使用“abc”作为字符串输入运行时,我得到以下返回:

VBA代码:Fsu0z3i6Ma5HCrP3eXucrdssJLc=
Python代码:IFxkS7B_ePtZrvU8sGmiaipTHio=

有没有人知道如何在VBA中计算一个等于Python输出的正确HMAC-SHA1?

编辑03/04/2014:
根据Alex K.的建议,我确保使用 http://thydzik.com中的代码将SharedSecretKey解码为Base64。我将函数DecodeBase64添加到下面的VBA代码中 由于此输出是正确的,但还不是URL安全的(因此与Python输出不同),我使用VBA Replace()函数将+替换为-和{{1}与/
这些解决方案共同产生了正确的输出,这是谷歌服务器所接受的。

使用的VBA脚本:

_

添加了在Base64中解码的代码:

Public Function Base64_HMACSHA1(ByVal sTextToHash As String, ByVal sSharedSecretKey As String)

Dim asc As Object, enc As Object
Dim TextToHash() As Byte
Dim SharedSecretKey() As Byte
Set asc = CreateObject("System.Text.UTF8Encoding")
Set enc = CreateObject("System.Security.Cryptography.HMACSHA1")

TextToHash = asc.Getbytes_4(sTextToHash)
SharedSecretKey = asc.Getbytes_4(sSharedSecretKey)
enc.Key = SharedSecretKey

Dim bytes() As Byte
bytes = enc.ComputeHash_2((TextToHash))
Base64_HMACSHA1 = EncodeBase64(bytes)
Set asc = Nothing
Set enc = Nothing

End Function

Private Function EncodeBase64(ByRef arrData() As Byte) As String

Dim objXML As MSXML2.DOMDocument
Dim objNode As MSXML2.IXMLDOMElement

Set objXML = New MSXML2.DOMDocument

' byte array to base64
Set objNode = objXML.createElement("b64")
objNode.DataType = "bin.base64"
objNode.nodeTypedValue = arrData
EncodeBase64 = objNode.Text

Set objNode = Nothing
Set objXML = Nothing

End Function

使用的Python脚本:

Private Function decodeBase64(ByVal strData As String) As Byte()
Dim objXML As MSXML2.DOMDocument
Dim objNode As MSXML2.IXMLDOMElement

Set objXML = New MSXML2.DOMDocument
Set objNode = objXML.createElement("b64")
objNode.DataType = "bin.base64"
objNode.Text = strData
decodeBase64 = objNode.nodeTypedValue


Set objNode = Nothing
Set objXML = Nothing
End Function

1 个答案:

答案 0 :(得分:3)

在这里,您从输入字符串中获取密钥:

SharedSecretKey = asc.Getbytes_4(sSharedSecretKey)

但是在这里你从Base64解码输入字符串:

decodedKey = base64.urlsafe_b64decode(privateKey)

.Net的Getbytes不会进行Base64解码,因此输入非常不同。

如果将SharedSecretKey解码为字节数组,您将获得正确的输出:

IFxkS7B/ePtZrvU8sGmiaipTHio=

虽然注意到不同的Base64重新编码由urlsafe_b64encode引起的语义。

(如果您通过Converter在.net中解码,则需要丢失密钥中的尾随填充=