You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用hashlib.sha1实现HMAC-SHA1时遇类型错误:无法拼接哈希对象与字节

解决HMAC-SHA1实现中的类型错误问题

问题根源

报错TypeError: can't concat _hashlib.HASH to bytes的核心原因:

  • 自定义的sha1函数返回的是_hashlib.HASH哈希实例对象,而非哈希计算后的字节串,导致无法和bytes类型数据直接拼接
  • 代码中多余的Base64编码完全没必要,会导致哈希结果和标准HMAC-SHA1不一致
  • 密钥处理分支中,当密钥长度超过块大小B时,同样试图将HASH对象与bytes拼接,触发类型错误

修正步骤

  1. 修复自定义sha1函数:让它返回哈希计算后的字节串(调用digest()方法),同时移除多余的Base64编码
  2. 修正hmac_sha1拼接逻辑:确保所有参与拼接的都是bytes类型
  3. 补充bxor函数:实现字节级的异或操作(代码中用到但未定义)

修正后的完整代码

import hashlib

def bxor(a, b):
    # 实现两个字节串的逐字节异或
    return bytes(x ^ y for x, y in zip(a, b))

def sha1(data):
    sha1_object = hashlib.sha1()
    sha1_object.update(data)
    # 返回哈希后的字节串,而非HASH对象
    return sha1_object.digest()

def hmac_sha1(data, key):
    IPAD = b'\x36' * 64
    OPAD = b'\x5C' * 64

    B = hashlib.sha1().block_size
    L = hashlib.sha1().digest_size
    
    if len(key) == B:
        K_exp = key
    elif len(key) > B:
        # 先哈希密钥得到字节串,再补零
        K_exp = sha1(key) + b'\x00' * (B - L)
    else:
        K_exp = key + b'\x00' * (B - len(key))

    # 所有操作均为字节串拼接,无HASH对象参与
    inner_hash = sha1(bxor(K_exp, IPAD) + data)
    return sha1(bxor(K_exp, OPAD) + inner_hash)

# 测试验证
if __name__ == "__main__":
    key = b'Test Key'
    data = b'Test Message'
    
    # 标准库结果
    standard_digester = hashlib.hmac.new(key, data, hashlib.sha1)
    standard_signature = standard_digester.digest()
    
    # 自定义实现结果
    custom_signature = hmac_sha1(data, key)
    
    assert custom_signature == standard_signature, "结果不一致!"
    print(f"签名验证通过,签名值:{custom_signature.hex()}")

关键说明

  • sha1函数现在返回digest()的字节串结果,满足后续拼接操作的类型要求
  • 移除了Base64编码,HMAC-SHA1直接对原始字节数据计算,无需额外编码
  • 密钥处理分支中,sha1(key)返回字节串,可与补零的bytes正常拼接
  • 补充的bxor函数确保字节异或操作能正确执行

内容的提问来源于stack exchange,提问作者quintus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:05:29