Python3下十六进制私钥转ASCII生成HMAC的API认证问题
解决Python3下API身份认证的HMAC签名问题
我猜你遇到的问题大概率是Python3对字符串和字节类型的严格区分导致的——毕竟Python2里字符串默认是字节序列,而Python3中str和bytes是完全不同的类型,hmac库在Python3里要求密钥和待签名消息都必须是bytes类型,这和Python2的宽松行为不一样。
先理清楚整个流程的正确步骤,再给你Python3的实现代码:
核心步骤拆解
- 第一步:把十六进制格式的私钥字符串解码为字节序列(这才是密钥的原始二进制形式)
- 第二步:准备好需要签名的消息内容(比如请求的URL、参数、时间戳等,具体要看API的要求),并转为字节序列
- 第三步:用
hmac结合API指定的哈希算法(比如SHA256)生成带密钥的哈希,再按需转为十六进制字符串或Base64(匹配API要求的请求头格式)
Python3 实现代码示例
假设API要求用SHA256算法生成HMAC签名,代码如下:
import hmac import hashlib import binascii # 你的十六进制私钥 hex_private_key = "665c20b3c4517e025311160b7fec3fdb9b4d091f142d308c568d0eec4745f569" # 1. 解码十六进制私钥为字节序列 private_key_bytes = binascii.unhexlify(hex_private_key) # 2. 准备待签名的消息(示例:假设是请求路径+时间戳,具体按API要求来) message = "/api/v1/resource?timestamp=1699999999" message_bytes = message.encode('utf-8') # 必须转为字节类型 # 3. 生成HMAC签名 hmac_signature = hmac.new(private_key_bytes, message_bytes, hashlib.sha256).digest() # 4. 如果API要求签名是十六进制字符串,就转成可读字符串 signature_hex = binascii.hexlify(hmac_signature).decode('utf-8') # 最后把签名放到HTTP请求头里,比如 Authorization: HMAC {signature_hex} print(f"生成的有效签名:{signature_hex}")
和Python2的差异点说明
- Python2中,
binascii.unhexlify返回的是str(本质是字节序列),hmac.new可以直接接收str作为密钥和消息;但Python3中,unhexlify返回bytes,hmac.new强制要求密钥和消息都必须是bytes,所以必须把字符串形式的消息用encode()转成字节。 - 如果在Python3中直接把十六进制字符串传给
hmac.new当密钥,相当于把每个字符的ASCII编码当作字节,这会导致密钥完全错误,签名自然无法通过API验证。
常见排查点
- 确认API要求的哈希算法(SHA1/SHA256/SHA512等),不要用错
- 待签名的消息内容必须和API要求完全一致(比如是否包含请求方法、路径、参数、时间戳,顺序是否正确)
- 签名的输出格式(原始字节、十六进制字符串还是Base64)要严格匹配API的要求
内容的提问来源于stack exchange,提问作者poply
相关产品推荐
相关产品推荐

