对于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
答案 0 :(得分:3)
在这里,您从输入字符串中获取密钥:
SharedSecretKey = asc.Getbytes_4(sSharedSecretKey)
但是在这里你从Base64解码输入字符串:
decodedKey = base64.urlsafe_b64decode(privateKey)
.Net的Getbytes
不会进行Base64解码,因此输入非常不同。
如果将SharedSecretKey
解码为字节数组,您将获得正确的输出:
IFxkS7B/ePtZrvU8sGmiaipTHio=
虽然注意到不同的Base64重新编码由urlsafe_b64encode
引起的语义。
(如果您通过Converter
在.net中解码,则需要丢失密钥中的尾随填充=