2013-07-22 61 views
1

我搜索並發現了幾個問題,這些問題解決了我正在努力完成的任務,但我似乎無法完全明白這一點。我是編程新手,正試圖複製供應商提供給我的少量代碼(PHP,Ruby,Perl,C#)。我已經採用了PHP代碼,並盡我所能在Python中複製它,並且除了這個簽名函數以外,已經完成了所有工作。基本上,我必須獲取用戶通過Web表單傳入的數據,對其進行簽名,然後將其發送給Web服務偵聽器進行處理。儘可能地嘗試,我不能得到簽名值匹配。不幸的是,供應商不提供代碼級別的支持,除了他們的樣品,所以我在那裏運氣不好。這裏的PHP示例:Python HMAC-SHA256簽名不同於PHP簽名

<?php 

define ('HMAC_SHA256', 'sha256'); 
define ('SECRET_KEY', 'secret_key_redacted'); 

function sign ($params) { 
    return signData(buildDataToSign($params), SECRET_KEY); 
} 

function signData($data, $secretKey) { 
    return base64_encode(hash_hmac('sha256', $data, $secretKey, true)); 
} 

function buildDataToSign($params) { 
     $signedFieldNames = explode(",",$params["signed_field_names"]); 
     foreach ($signedFieldNames as &$field) { 
      $dataToSign[] = $field . "=" . $params[$field]; 
     } 
     return commaSeparate($dataToSign); 
} 

function commaSeparate ($dataToSign) { 
    return implode(",",$dataToSign); 
} 

?> 

被調用爲這樣:

<?php 
foreach($params as $name => $value) { 
    echo "<input type=\"text\" id=\"" . $name . "\" name=\"" . $name . "\" value=\"" . $value . "\"/>\n"; 
} 

echo "<input type=\"text\" id=\"signature\" name=\"signature\" value=\"" . sign($params) . "\"/>\n"; 
?> 

這是我在Python已經用於試圖複製:

def payment_confirmation(self, *args, **kw): 
vars = cherrypy.request.params #takes POST parameters from previous page 
del vars['submit'] #removed so it doesnt get signed - part of POST from prev. page 

def sign_data(vars): 
    for key, value in vars.iteritems(): 
     yield "%s=%s," % (key, value) 

sign_payload = ''.join(sign_data(vars)).rstrip(',') 
sign_signature = hashlib.sha256(sign_payload + secret_key).digest().encode('base64') 

這裏是一個樣本我試圖簽署的數據(減少到通過Python代碼中的sign_data()方法返回的對象中:

access_key=12345,reference_number=123456789,currency=USD,locale=en,profile_id=1234567,transaction_type=authorization,signed_date_time=2013-07-22T16:30:43Z,amount=25.00,transaction_uuid=0dc4a151-f2ec-11e2-bb29-005056c00008,payment_method=card,signed_field_names=access_key,profile_id,transaction_uuid,payment_token,signed_field_names,signed_date_time,locale,payment_method,transaction_type,amount,reference_number,currency,payment_token=0000000000000000 

我意識到這是一個很長的鏡頭,但是有沒有人看到我的Python中的簽名方法與PHP中提供的方法顯然不正確?我認爲這可能是PHP函數對鍵值對進行編碼的一種方式,所以我試圖在Python代碼中搞亂,但似乎沒有奏效。提前致謝!

回答

1

如果你還停留在那個問題,你可能想使用嘗試:

sign_signature = base64.b64encode(hmac.new(secret_key, sign_payload, hashlib.sha256).hexdigest())

這裏的關鍵是使用hexdigest()而不是digest()

在我的情況下,我失去了2個小時,發現爲什麼Python沒有產生與PHP嘗試用新的「應用程序祕密證明」簽署Facebook API請求時所產生的結果相同的結果。

+2

爲什麼b64encode是十六進制的? Facebook不希望你,爲一。 參見https://github.com/pythonforfacebook/facebook-sdk/commit/157799da3bb725b6b2f8698f7ee53b4d0e2abf2c其使用 hmac.new(app_secret.encode( 'ASCII'), 味精= access_token.encode( 'ASCII'), digestmod = hashlib.sha256).hexdigest() – drewp