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

使用fastecdsa实现ScroogeCoin时签名报错:无法将整数转字节

ScroogeCoin实现中fastecdsa签名报错排查

问题详情

使用fastecdsa库实现ScroogeCoin时,调用create_coins函数触发类型错误,报错指向签名代码tx["signature"] = ecdsa.sign(...),提示无法将整数转换为字节。已尝试对tx["hash"]使用encode()、bytes.fromhex()等转换方式,仍未解决。

相关代码

import hashlib
import json
from fastecdsa import keys, curve, ecdsa


class ScroogeCoin(object):
    def __init__(self):
        self.private_key, self.public_key = keys.gen_keypair(curve.secp256k1) 
        self.address = hashlib.sha256(json.dumps(self.public_key.x).encode()).hexdigest()
        self.chain = [] 
        self.current_transactions = []

    def create_coins(self, receivers: dict):
        """Scrooge adds value to some coins"""
        tx = {
            "sender" : self.address,
            "location": {"block": -1, "tx": -1},
            "receivers" : receivers,
        }

        tx["hash"] = hashlib.sha256(json.dumps(tx).encode()).hexdigest()
        tx["signature"] = ecdsa.sign(self.private_key, tx["hash"])

        self.current_transactions.append(tx)
        ...

报错信息

Traceback (most recent call last):
  File "D:\Scrooge_coin_assignmnet.py", line 216, in <module>
    main()
  File "D:\Scrooge_coin_assignmnet.py", line 197, in main
    Scrooge.create_coins({users[0].address:10, users[1].address:20, users[3].address:50})
  File "D:\Scrooge_coin_assignmnet.py", line 27, in create_coins
    tx["signature"] = ecdsa.sign(self.private_key, tx["hash"])# signed hash of tx
  File "C:\Users\d\AppData\Local\Programs\Python\Python311\Lib\site-packages\fastecdsa\ecdsa.py", line 36, in sign
    rfc6979 = RFC6979(msg, d, curve.q, hashfunc, prehashed=prehashed)
  File "C:\Users\d\AppData\Local\Programs\Python\Python311\Lib\site-packages\fastecdsa\util.py", line 25, in __init__
    self.msg = msg_bytes(msg)
  File "C:\Users\d\AppData\Local\Programs\Python\Python311\Lib\site-packages\fastecdsa\util.py", line 153, in msg_bytes
    raise ValueError('Msg "{}" of type {} cannot be converted to bytes'.format(
ValueError: Msg "21783419755125685845542189331366569080312572314742637241373298325693730090205" of type <class 'int'> cannot be converted to bytes

错误原因

  1. 参数顺序完全颠倒:fastecdsa的ecdsa.sign函数定义为sign(msg, d, curve=curve.P256, ...),第一个参数是待签名的消息,第二个参数是私钥。当前代码把私钥放在第一个参数位置,交易哈希放在第二个,导致私钥被当作消息处理,而哈希字符串被误解析为整数,触发类型错误。
  2. 哈希格式处理不当:即使参数顺序正确,直接传入十六进制哈希字符串也会导致库尝试将其解析为整数,需要传递字节类型的哈希值,或配合prehashed=True参数使用。

解决方案

修改签名代码的参数顺序,并正确处理哈希的字节格式,同时利用prehashed=True跳过重复哈希(因为我们已经对交易做了SHA256哈希):

修改后的create_coins函数

def create_coins(self, receivers: dict):
    """Scrooge adds value to some coins"""
    tx = {
        "sender" : self.address,
        "location": {"block": -1, "tx": -1},
        "receivers" : receivers,
    }

    # 直接获取字节类型的SHA256哈希,同时存十六进制字符串到tx["hash"]
    tx_hash_bytes = hashlib.sha256(json.dumps(tx).encode()).digest()
    tx["hash"] = tx_hash_bytes.hex()
    
    # 修正参数顺序:消息在前,私钥在后,指定曲线并启用prehashed
    tx["signature"] = ecdsa.sign(tx_hash_bytes, self.private_key, curve=curve.secp256k1, prehashed=True)
    
    self.current_transactions.append(tx)

关键说明

  • 调整ecdsa.sign的参数顺序是核心修复点,必须保证消息(哈希值)在前,私钥在后。
  • 使用digest()获取字节哈希比先转十六进制再转回字节更高效,也避免字符串解析错误。
  • prehashed=True告诉库我们传入的已经是哈希后的结果,不需要再对消息执行哈希操作,符合签名逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:31:01