2014-02-26 1 views
3

Google Maps Business API 쿼리의 경우 HMAC-SHA1을 사용하여 모든 쿼리에 디지털 서명해야합니다. VBA 매크로가있는 Excel 파일을 사용하여 쿼리를 보내고 출력을 구문 분석하므로 VBA에서 서명을 만들고 싶습니다. 이 질문 + 답변을 찾았습니다. Base64 HMAC SHA1 String in VBA
그러나 Google API로 쿼리를 보내면이 코드의 문자열 서명이 유효하지 않습니다.

Google은 몇 가지 샘플 스크립트를 제공합니다. 위의 VBA 코드를 테스트 할 때 사용했던 것과 동일한 입력을 사용하여 Python sample script을 테스트했으며 이 유효한 서명을 반환했습니다. 따라서 제공된 VBA 코드가 적절한 HMAC-SHA1 서명을 구성하지 못하는 것 같지만 문제를 찾을 수 없습니다 (암호화에 대한 경험이없고 기본적인 VBA 지식 만 있습니다).
HMAC-SHA1 VBA의 URL 암호화가 잘못된 출력을 생성합니다.

VBA 코드 : Fsu0z3i6Ma5HCrP3eXucrdssJLc=
파이썬 나는 다음과 같은 수익을 얻을 문자열 입력으로 "abc"로 실행하면 1412SxPev45oMMRQSXazwQp789yM=
:

내가 테스트 목적으로 HMAC-SHA1 키를 생성 코드 : IFxkS7B_ePtZrvU8sGmiaipTHio=

누구나 파이썬 출력과 동일한 VBA에서 올바른 HMAC-SHA1을 계산하는 방법을 알고 있습니까? ?

편집 2014년 3월 4일 : 알렉스 K.의 제안 당
, 나는 http://thydzik.com에서 코드를 사용하여, Base64로에 SharedSecretKey를 디코딩 확인했다. 아래의 VBA 코드에 DecodeBase64 함수를 추가했습니다. 이 출력은 정확하지만 아직 URL 세이프 (파이썬 출력하므로 동일하지 않음) 이었기 때문에
는 I 함께 올바른 출력을 생성 _
이러한 솔루션 -/+를 교체 VBA Replace() 함수를 사용하는 Google 서버에서 허용됩니다.

사용 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 

추가 코드 :

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 

사용 파이썬 스크립트 : 여기

#!/usr/bin/python 
# coding: utf8 

import sys 
import hashlib 
import urllib 
import hmac 
import base64 
import urlparse 

print("") 
print("URL Signer 1.0") 
print("") 

# Convert the URL string to a URL, which we can parse 
# using the urlparse() function into path and query 
# Note that this URL should already be URL-encoded 
url = urlparse.urlparse("YOUR_URL_TO_SIGN") 

privateKey = "YOUR_PRIVATE_KEY" 

# We only need to sign the path+query part of the string 
urlToSign = url.path + "?" + url.query 

# Decode the private key into its binary format 
decodedKey = base64.urlsafe_b64decode(privateKey) 

# Create a signature using the private key and the URL-encoded 
# string using HMAC SHA1. This signature will be binary. 
signature = hmac.new(decodedKey, urlToSign, hashlib.sha1) 

# Encode the binary signature into base64 for use within a URL 
encodedSignature = base64.urlsafe_b64encode(signature.digest()) 
originalUrl = url.scheme + "://" + url.netloc + url.path + "?" + url.query 
print("Full URL: " + originalUrl + "&signature=" + encodedSignature) 

답변

3

당신이

SharedSecretKey = asc.Getbytes_4(sSharedSecretKey) 

을하지만, 여기에 당신이 Base64로에서 입력 문자열을 디코딩하는 경우 취득 : 입력 문자열에서 키를 획득

decodedKey = base64.urlsafe_b64decode(privateKey) 

닷넷의 Getbytes 것이다 입력이 매우 다르기 때문에하지 Base64로 디코딩.

당신이 바이트 배열로 SharedSecretKey를 디코딩 할 경우, 올바른 출력을 얻을 것이다 :

IFxkS7B/ePtZrvU8sGmiaipTHio= 

urlsafe_b64encode로 인해 다른 Base64로 재 인코딩의 의미를주의 있지만.

(당신이 Converter을 통해 .NET에서 디코딩 경우 키에서 후행 패딩 =을 잃게해야합니다)

관련 문제