首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python HMAC-SHA256签名与PHP签名不同

Python HMAC-SHA256签名与PHP签名不同
EN

Stack Overflow用户
提问于 2013-07-23 00:56:07
回答 1查看 2.3K关注 0票数 1

我搜索并找到了一些问题,这些问题似乎解决了我试图实现的目标,但我似乎不太清楚这一点。我是编程新手,正在尝试用几种语言(PHP、Ruby、Perl、C#)复制供应商提供给我的一些代码。我已经获取了PHP代码,并尽最大努力将其复制到Python中,并且除了这个签名函数之外,一切都正常工作。基本上,我必须获取用户通过web表单传入的一组数据,对其进行签名,然后将其发送到web服务侦听器进行处理。尽管我可能会尝试,但我无法获得匹配的签名值。不幸的是,除了他们的示例之外,供应商没有提供任何代码级的支持,所以我在这方面不太走运。下面是PHP示例:

代码语言:javascript
复制
<?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);
}

?>

它是这样调用的:

代码语言:javascript
复制
<?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中用来尝试复制的代码:

代码语言:javascript
复制
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()方法返回的对象:

代码语言:javascript
复制
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代码中对其进行修改,但似乎不起作用。提前感谢!

EN

回答 1

Stack Overflow用户

发布于 2013-11-06 04:08:44

如果你仍然被这个问题卡住了,你可以试着使用:

代码语言:javascript
复制
sign_signature = base64.b64encode(hmac.new(secret_key, sign_payload, hashlib.sha256).hexdigest())

这里的关键是使用hexdigest()而不是digest()

在我的例子中,我花了2个小时来弄清楚为什么Python在尝试使用新的“应用程序秘密证明”对Facebook API请求进行签名时,不能产生与PHP相同的结果。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17793194

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档