BIP-0039助记词23词推导第24校验词代码错误排查求助
BIP39助记词第24个校验词推导错误修复
问题描述
给定有效BIP39助记词:
cute door network found clown neither slight common torch tissue project melt bottom marble tunnel aisle kitchen staff only unhappy measure census need miss
使用下方Python代码从前23个词推导第24个校验词时,输出结果为"type",与正确结果不符。
原错误代码
import hashlib def get_checksum_word(words_path: str): with open(words_path, 'r') as f: word_list = f.read().splitlines() # Get the first 23 words of the mnemonic mnemonic = input("Enter 23 words separated by spaces: ") words = mnemonic.strip().split() if len(words) != 23: raise ValueError("Invalid number of words in mnemonic") # Generate the binary string from the first 23 words binary_str = '' for word in words: index = word_list.index(word) + 1 print(index) binary_str += bin(index)[2:].zfill(11) entropy_length = len(binary_str) # Calculate the checksum entropy_bytes = b'' for i in range(0, entropy_length, 8): byte = int(binary_str[i:i+8], 2).to_bytes(1, 'big') entropy_bytes += byte checksum = hashlib.sha256(entropy_bytes).digest()[0] binary_str += bin(checksum)[2:].zfill(8) # Get the index of the 24th word index = int(binary_str[-11:], 2) word = word_list[index] print("The 24th word is:", word)
错误原因分析
- 词表索引错误:BIP39词表索引从0开始(0-2047对应2048个词),每个词对应11位二进制值。原代码中
index = word_list.index(word) + 1错误地将索引加1,导致生成的二进制串完全偏离正确值,这是核心错误。 - 熵处理逻辑错误:23个词对应253位二进制串,原代码直接按8位一组转换为字节,而253不是8的整数倍,最后一组仅5位,转换时自动补前导0,导致熵值被篡改,后续校验位计算完全错误。
- 校验位拼接错误:BIP39中24词助记词的校验位仅8位,原代码直接将完整8位校验位拼接到253位串后,总长度为261位,无法正确拆分出最后11位的校验词索引。
修正后的代码
import hashlib def get_checksum_word(words_path: str): with open(words_path, 'r') as f: word_list = f.read().splitlines() mnemonic = input("Enter 23 words separated by spaces: ") words = mnemonic.strip().split() if len(words) != 23: raise ValueError("Invalid number of words in mnemonic") # 将每个词转换为11位二进制串(使用词表原始索引,从0开始) binary_str = '' for word in words: idx = word_list.index(word) binary_str += bin(idx)[2:].zfill(11) # 遍历熵的最后3位所有可能(0-7,共8种),找到符合校验规则的组合 for e_suffix in range(8): e_suffix_bin = bin(e_suffix)[2:].zfill(3) # 拼接得到完整的256位熵二进制串 full_entropy_bin = binary_str + e_suffix_bin # 转换为字节用于SHA256计算 entropy_bytes = bytes(int(full_entropy_bin[i:i+8], 2) for i in range(0, 256, 8)) # 计算SHA256哈希,提取前8位作为校验位 sha256_hash = hashlib.sha256(entropy_bytes).digest() checksum_bin = bin(sha256_hash[0])[2:].zfill(8) # 拼接熵的最后3位和校验位,得到第24个词的11位二进制索引 last_word_bin = e_suffix_bin + checksum_bin last_word_idx = int(last_word_bin, 2) # 验证生成的完整助记词是否符合BIP39校验规则 full_mnemonic_bin = binary_str + last_word_bin verify_entropy_bin = full_mnemonic_bin[:256] verify_checksum_bin = full_mnemonic_bin[256:] verify_entropy_bytes = bytes(int(verify_entropy_bin[i:i+8], 2) for i in range(0, 256, 8)) calculated_checksum_bin = bin(hashlib.sha256(verify_entropy_bytes).digest()[0])[2:].zfill(8)[:8] if verify_checksum_bin == calculated_checksum_bin: print("The 24th word is:", word_list[last_word_idx]) return raise ValueError("Invalid 23 words, no valid checksum word found")
修正说明
- 移除了索引加1的错误,直接使用词表原始索引生成二进制串。
- 按照BIP39规范,23个词对应熵的前253位,遍历熵最后3位的所有可能(共8种),计算对应的校验位并验证。
- 增加了校验验证步骤,确保生成的第24个词符合BIP39规则。
内容的提问来源于stack exchange,提问作者user713813
相关产品推荐
相关产品推荐

