2013-07-22 2 views
1

Я искал и нашел несколько вопросов, которые были адресованы тем, что я пытаюсь выполнить, но я не могу сказать, что это не так. Я новичок в программировании и пытаюсь реплицировать немного кода, доступного мне продавцом на нескольких языках (PHP, Ruby, Perl, C#). Я взял PHP-код и попытался изо всех сил реплицировать его на Python и получил все, кроме этой функции подписи. В принципе, я должен взять массив данных, которые передаются пользователем через веб-форму, подписывать ее и отправлять ее слушателю веб-сервисов для обработки. Попытайтесь, как я мог, я не могу получить значения подписи для соответствия. Поставщик, к сожалению, не предоставляет поддержку уровня кода для чего-либо другого, кроме своих образцов, поэтому мне там не повезло. Вот 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') 

Вот образец данные, которые я пытаюсь подписать (сведены в объект, возвращаемый с помощью метода sign_data() в коде Python:

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 hexdigest? Facebook не хочет, чтобы вы, для одного. См https://github.com/pythonforfacebook/facebook-sdk/commit/157799da3bb725b6b2f8698f7ee53b4d0e2abf2c, который использует hmac.new (app_secret.encode ('ASCII'), тзд = access_token.encode ('ASCII'), digestmod = hashlib.sha256) .hexdigest() – drewp

Смежные вопросы