Base58Check格式转换异常:编码后解码提示校验和无效求助
Base58Check编码解码校验和错误问题修复
问题背景
尝试将指定整数通过Base58Check编码为字符串,但解码时始终提示「无效校验和」错误,涉及编码、解码、私钥生成三类代码均存在逻辑问题。使用的整数为:111383925596674021496745350149385052040158942814438962455769092527167857754112
原编码代码
import hashlib import base58 code_string = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" def convert_bytes_to_base58check(hash_result, num_leading_zero_bytes): x = int.from_bytes(hash_result, byteorder="big") output_string = "" while x > 0: x, remainder = divmod(x, 58) output_string += code_string[remainder] output_string += code_string[0] * num_leading_zero_bytes return output_string[::-1] my_integer = 111383925596674021496745350149385052040158942814438962455769092527167857754112 my_hex_string = hex(my_integer)[2:] if len(my_hex_string) % 2 != 0: my_hex_string = "0" + my_hex_string my_bytes = bytes.fromhex(my_hex_string) my_hash = hashlib.sha256(hashlib.sha256(my_bytes).digest()).digest() output_string = convert_bytes_to_base58check(my_hash, 0) print(output_string)
原解码代码
import base58 code_string = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" def convert_bytes_to_big_integer(data): return int.from_bytes(data, byteorder='big') def encode_base58check(hash_result, num_leading_zero_bytes): x = convert_bytes_to_big_integer(hash_result) output_string = "" while x > 0: x, remainder = divmod(x, 58) output_string += code_string[remainder] output_string += code_string[0] * num_leading_zero_bytes return output_string[::-1] my_string = 'GTbisRUFDyw71dQcDXfMbYK6hMQ1EcnTvTmvGa5LodBp' my_bytes = base58.b58decode_check(my_string) my_hash = my_bytes[:-4] num_leading_zero_bytes = my_bytes[-1] output_string = encode_base58check(my_hash, num_leading_zero_bytes) print(output_string)
原私钥生成代码
from bitcoin import * import base58 def getPrivateKey(my_integer): print(type(my_integer)) print("number = ",my_integer) public_key = privtopub(my_integer) uncompressed_address = pubtoaddr(public_key) compressed_public_key = compress(public_key) compressed_address = pubtoaddr(compressed_public_key) my_hex_string = hex(my_integer)[2:] print("hex_string = ",my_hex_string) if len(my_hex_string) % 2 != 0: my_hex_string = "0" + my_hex_string my_bytes = bytes.fromhex(my_hex_string) my_bytes_with_prefix = b"\x80" + my_bytes my_bytes_with_prefix_and_checksum = my_bytes_with_prefix + b"\x01" + bin_sha256(bin_sha256(my_bytes_with_prefix))[:4] my_private_key = base58.b58encode(my_bytes_with_prefix_and_checksum) print(my_private_key)
问题分析
编码代码核心错误:
- 错误地将双重SHA256的哈希结果直接编码,而非将**原始数据+校验和(哈希前4字节)**的组合体进行Base58编码。
- 前导零字节处理逻辑颠倒,导致编码结果无法正确对应原始数据的前导零。
解码代码核心错误:
- 误解
base58.b58decode_check的返回值:该函数返回的是已验证校验和并去除校验和后的原始数据,而非带校验和的完整数据,因此my_bytes[:-4]是错误操作。 - 从
my_bytes[-1]提取前导零字节数的逻辑完全不符合Base58Check规范。
- 误解
私钥生成代码核心错误:
- 计算校验和时仅基于
前缀+私钥,而非前缀+私钥+压缩标记(0x01)的完整数据,导致校验和不匹配。
- 计算校验和时仅基于
修复后的代码
修复版编码代码
import hashlib code_string = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" def encode_base58check(data): # 计算校验和:双重SHA256取前4字节 checksum = hashlib.sha256(hashlib.sha256(data).digest()).digest()[:4] # 拼接原始数据与校验和 data_with_checksum = data + checksum # 统计前导零字节数 num_leading_zeros = 0 while num_leading_zeros < len(data_with_checksum) and data_with_checksum[num_leading_zeros] == 0: num_leading_zeros += 1 # 转换为大整数 x = int.from_bytes(data_with_checksum, byteorder="big") output = [] while x > 0: x, remainder = divmod(x, 58) output.append(code_string[remainder]) # 补充前导零对应的Base58前缀字符 output.extend([code_string[0]] * num_leading_zeros) # 反转得到最终编码结果 return ''.join(reversed(output)) # 目标整数 my_integer = 111383925596674021496745350149385052040158942814438962455769092527167857754112 # 转换为32字节标准私钥格式 my_bytes = my_integer.to_bytes(32, byteorder='big') # 编码整数本身(无前缀) encoded_integer = encode_base58check(my_bytes) print("编码后的整数:", encoded_integer) # 编码压缩格式私钥(带0x80前缀和0x01压缩标记) compressed_privkey_data = b"\x80" + my_bytes + b"\x01" encoded_compressed_privkey = encode_base58check(compressed_privkey_data) print("压缩私钥编码结果:", encoded_compressed_privkey)
修复版解码代码
import hashlib code_string = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" def decode_base58check(s): # 将Base58字符串转换为大整数 x = 0 for c in s: x = x * 58 + code_string.index(c) # 转换为字节(自动补位) data_with_checksum = x.to_bytes((x.bit_length() + 7) // 8, byteorder='big') # 统计Base58字符串中的前缀零字符数 num_leading_zeros = 0 while num_leading_zeros < len(s) and s[num_leading_zeros] == code_string[0]: num_leading_zeros += 1 # 补上前导零字节 data_with_checksum = b'\x00' * num_leading_zeros + data_with_checksum # 拆分原始数据与校验和 data = data_with_checksum[:-4] checksum = data_with_checksum[-4:] # 验证校验和 expected_checksum = hashlib.sha256(hashlib.sha256(data).digest()).digest()[:4] if checksum != expected_checksum: raise ValueError("无效校验和") return data # 待解码字符串 my_string = 'GTbisRUFDyw71dQcDXfMbYK6hMQ1EcnTvTmvGa5LodBp' try: decoded_data = decode_base58check(my_string) print("解码后原始数据(十六进制):", decoded_data.hex()) # 若为压缩私钥,提取原始整数 if len(decoded_data) == 34 and decoded_data[0] == 0x80 and decoded_data[-1] == 0x01: privkey_integer = int.from_bytes(decoded_data[1:-1], byteorder='big') print("提取的私钥整数:", privkey_integer) except ValueError as e: print("解码失败:", e)
修复版私钥生成代码
from bitcoin import * import hashlib import base58 def getPrivateKey(my_integer): print("整数类型:", type(my_integer)) print("私钥整数:", my_integer) # 生成公钥及地址 public_key = privtopub(my_integer) uncompressed_address = pubtoaddr(public_key) compressed_public_key = compress(public_key) compressed_address = pubtoaddr(compressed_public_key) print("非压缩地址:", uncompressed_address) print("压缩地址:", compressed_address) # 转换为32字节标准私钥字节 my_bytes = my_integer.to_bytes(32, byteorder='big') print("私钥十六进制:", my_bytes.hex()) # 生成压缩私钥 compressed_data = b"\x80" + my_bytes + b"\x01" compressed_checksum = hashlib.sha256(hashlib.sha256(compressed_data).digest()).digest()[:4] compressed_privkey = base58.b58encode(compressed_data + compressed_checksum).decode('utf-8') print("压缩私钥:", compressed_privkey) # 生成非压缩私钥 uncompressed_data = b"\x80" + my_bytes uncompressed_checksum = hashlib.sha256(hashlib.sha256(uncompressed_data).digest()).digest()[:4] uncompressed_privkey = base58.b58encode(uncompressed_data + uncompressed_checksum).decode('utf-8') print("非压缩私钥:", uncompressed_privkey) # 调用示例 my_integer = 111383925596674021496745350149385052040158942814438962455769092527167857754112 getPrivateKey(my_integer)
内容的提问来源于stack exchange,提问作者timp bill
相关产品推荐
相关产品推荐

