Python HMAC哈希值编码为base64

6

我正尝试使用Django中间件完成Twitter身份验证。在此过程中,我按照这个链接(https://dev.twitter.com/oauth/overview/creating-signatures)的方式计算请求的签名:

    key = b"MY_KEY&"
    raw_init = "POST" + "&" + quote("https://api.twitter.com/1.1/oauth/request_token", safe='')

    raw_params = <some_params>
    raw_params = quote(raw_params, safe='')

    #byte encoding for HMAC, otherwise it returns "expected bytes or bytearray, but got 'str'"
    raw_final = bytes(raw_init + "&" + raw_params, encoding='utf-8')

    hashed = hmac.new(key, raw_final, sha1)

    request.raw_final = hashed

    # here are my problems: I need a base64 encoded string, but get the error "'bytes' object has no attribute 'encode'"
    request.auth_header = hashed.digest().encode("base64").rstrip('\n')

正如您所看到的,无法对“bytes”对象进行base64编码。

提出的解决方案在这里:在Python中实现HMAC-SHA1


你尝试过使用 base64.encodestring(str(raw_final)) 吗? - Jean-François Fabre
@Jean-FrançoisFabre,为什么我要对raw_final进行编码?我需要将HMAC对象转换为base64字符串...所有这些都是根据Twitter文档 - https://dev.twitter.com/oauth/overview/creating-signatures页面底部的说明。 - massive_dynamic
2个回答

9

诀窍在于直接使用base64模块而不是str / byte编码,它支持二进制。

您可以像这样适配它(未在您的上下文中测试,应该可以工作):

import base64
#byte encoding for HMAC, otherwise it returns "expected bytes or bytearray, but got 'str'"
raw_final = bytes(raw_init + "&" + raw_params, encoding='utf-8')

hashed = hmac.new(key, raw_final, sha1)

request.raw_final = hashed

# here directly use base64 module, and since it returns bytes, just decode it
request.auth_header = base64.b64encode(hashed.digest()).decode()

以下是一个独立且可运行的测试示例(兼容python 3,Python 2.x用户在创建bytes字符串时需要删除“ascii”参数):

from hashlib import sha1
import hmac
import base64

# key = CONSUMER_SECRET& #If you dont have a token yet
key = bytes("CONSUMER_SECRET&TOKEN_SECRET","ascii")


# The Base String as specified here:
raw = bytes("BASE_STRING","ascii") # as specified by oauth

hashed = hmac.new(key, raw, sha1)

print(base64.b64encode(hashed.digest()).decode())

抱歉,我可以理解中文并进行翻译,但我无法直接处理HTML标记。请提供更具体的翻译请求。
Rh3xUffks487KzXXTc3n7+Hna6o=

PS:你提供的答案不再适用于Python 3,它仅适用于Python 2。


1

我只是想为Python3调整答案。

from hashlib import sha512
import hmac
import base64


key = b"KEY"
path = b"WHAT YOU WANT TO BE SIGNED"

hashed = hmac.new(key, path, sha512).digest()

print(base64.b64encode(hashed))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接