1

I searched and found a few questions that sort of addressed what I am trying to accomplish, but I can't seem to quite put my finger on this. I'm new to programming and am trying to replicate a bit of code that's available to me by the vendor in a handful of languages (PHP, Ruby, Perl, C#). I've taken the PHP code and tried my best to replicate it in Python and have gotten everything working except this signature function. Basically, I have to take an array of data that's being passed in by a user via web form, sign it, and send it to the web services listener to process. Try as I might, I can't get the signature values to match. The vendor unfortunately does not provide code-level support for anything other than their samples, so I'm out of luck there. Here's the PHP sample:

<?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);
}

?>

which is invoked as such:

<?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";
?>

This is what I've used in Python to attempt to replicate:

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')

Here's a sample of the data I'm trying to sign (reduced into the object that's being returned via the sign_data() method in the Python code:

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

I realize it's a long-shot, but does anyone see anything that's obviously incorrect about my signature method in Python vs. the provided method in PHP? I thought it could be a way that the PHP function is encoding the key-value pairs so I tried messing around with that in the Python code but it doesn't seem to have worked. Thanks in advance!

1 Answer 1

1

In case you're still stuck on that question, you might want to try using:

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

The key here is to use hexdigest() instead of digest().

In my case I lost 2 hours finding out why Python did not produce the same result as PHP did when trying to sign Facebook API requests with their new "app secret proof".

Sign up to request clarification or add additional context in comments.

1 Comment

Why b64encode a hexdigest? Facebook doesn't want you to, for one. See github.com/pythonforfacebook/facebook-sdk/commit/… which uses hmac.new(app_secret.encode('ascii'), msg=access_token.encode('ascii'), digestmod=hashlib.sha256).hexdigest()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.