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

生成比特币地址时fromhex()非十六进制字符错误求助

比特币地址生成程序偶发非十六进制字符错误

问题代码

生成私钥的方法:

def get_private_key():
    while (True):
        random_str = os.urandom(256 // 8) + str(random.random()).encode() + str(time.time()).encode()
        random_num = hashlib.sha256(random_str).digest()
        private_key = int.from_bytes(random_num, 'big')
        if private_key < q-1:
            break
    return private_key

生成压缩公钥的方法:

def get_compressed_public_key(key):
    public_key = double_and_add(key, G)
    if public_key[1] % 2 == 0 :
        return "02" + str(hex(public_key[0]))[2:]
    else :
        return "03" + str(hex(public_key[0]))[2:]

生成比特币地址的核心方法:

def hash160(data):
    sha256_hash = SHA256.new(data)
    ripemd160_hash = RIPEMD160.new(sha256_hash.digest())
    return ripemd160_hash.hexdigest()

def generate_bitcoin_address(key):
    # Generate compressed public key
    hex_val = int(key, 16)
    compressed_pkey = get_compressed_public_key(hex_val)
    data = bytes.fromhex(compressed_pkey)
    hash160_val = "00" + hash160(data)
    print("Public Key's hash =", hash160_val)
    # Get Checksum Value
    sha256_first = SHA256.new(bytes.fromhex(hash160_val))
    sha256_second = SHA256.new(bytes.fromhex(sha256_first.hexdigest()))
    checksum = sha256_second.hexdigest()[:8]
    # Returns 25byte Bitcoin Address.
    return hash160_val + checksum

运行代码:

for i in range(100):
    private_key = str(hex(get_private_key()))[2:]
    address = generate_bitcoin_address(private_key)

错误信息

偶发如下报错:

Public key's hash = 00ededa6d1865639736123207949b0d57dfaf007ed
Public key's hash = 000069e3aabbec21d1332740e1440c651c48709819
...
Traceback (most recent call last):
  File "c:\Users\asn68\Desktop\a\2.py", line 112, in <module>
    address = generate_bitcoin_address(private_key)
  File "c:\Users\asn68\Desktop\a\2.py", line 86, in generate_bitcoin_address
    data = bytes.fromhex(compressed_pkey)
ValueError: non-hexadecimal number found in fromhex() arg at position 65

错误原因

问题出在get_compressed_public_key方法中:

  • SECP256K1的公钥x坐标是256位整数,但其十六进制表示长度可能不足64位(当高位有0时,hex()函数不会自动补前导零)。
  • 例如,若x坐标的十六进制是63个字符,拼接"02"/"03"后总长度为65(奇数),bytes.fromhex()要求输入字符串长度为偶数,单个字符无法解析为一个字节,因此触发错误(Python错误提示表述不够直观,实际是长度不匹配导致解析失败)。

修复方案

修改get_compressed_public_key方法,确保x坐标的十六进制字符串固定为64位,不足时补前导零:

def get_compressed_public_key(key):
    public_key = double_and_add(key, G)
    # 格式化x坐标为64位十六进制字符串,自动补前导零
    x_hex = format(public_key[0], '064x')
    if public_key[1] % 2 == 0 :
        return "02" + x_hex
    else :
        return "03" + x_hex

使用format(num, '064x')可以保证输出的十六进制字符串恰好64位,拼接后总长度为66(对应33字节的压缩公钥),满足bytes.fromhex()的要求,彻底解决偶发错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:24:59