For Google Maps Business API requests, I need to sign each request using HMAC-SHA1. We use an Excel file with a VBA macro to send requests and analyze the output, so I would like to create a signature in VBA. I found this question + answer: Base64 HMAC SHA1 String in VBA
However, the string signature of this code is not valid when sending a request to the Google API.
Google provides some sample scripts. I tested a Python script sample with the same input that I used to test the VBA code above, and the Python codereturn a valid signature. Therefore, it seems that the VBA code provided does not create the correct HMAC-SHA1 signature, but I can not find the problem (I have no encryption experience and only basic VBA knowledge).
I created the HMAC-SHA1 key for testing: 1412SxPev45oMMRQSXazwQp789yM=
When I start with " abc" as a string input, I get the following returns:
VBA code: Fsu0z3i6Ma5HCrP3eXucrdssJLc=
Python code: IFxkS7B_ePtZrvU8sGmiaipTHio=
Does anyone know how to calculate the correct HMAC-SHA1 in VBA that equals Python output?
Edit 04/03/2014:
At the suggestion of Alex K., I made sure to decrypt the SharedSecretKey for Base64 using the code fromhttp://thydzik.com . I have added a function DecodeBase64to the VBA code below.
Since this output was correct, but not yet safe for the URL (so it was not the same Python output), I used the VBA function Replace()to replace +with -and /with. _
These decisions together create the correct output that is accepted by Google servers.
Used VBA script:
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
Added code for decoding in Base64:
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
Python script used:
import sys
import hashlib
import urllib
import hmac
import base64
import urlparse
print("")
print("URL Signer 1.0")
print("")
url = urlparse.urlparse("YOUR_URL_TO_SIGN")
privateKey = "YOUR_PRIVATE_KEY"
urlToSign = url.path + "?" + url.query
decodedKey = base64.urlsafe_b64decode(privateKey)
signature = hmac.new(decodedKey, urlToSign, hashlib.sha1)
encodedSignature = base64.urlsafe_b64encode(signature.digest())
originalUrl = url.scheme + "://" + url.netloc + url.path + "?" + url.query
print("Full URL: " + originalUrl + "&signature=" + encodedSignature)
source
share