BIP39 校验和有时会失败
BIP39 Checksum fails sometimes
我有这段代码,将用于根据BIP39 Spec实现助记词生成器。
问题是大多数时候校验和不正确,但在某些情况下它有效,这取决于给定的熵。 (我使用 iancoleman.io bip39 来测试我的校验和)。
观察到以下情况:
使用了 128 位的熵。
Correct
Entropy: 10111101100010110111100011101111111110100010000101111110100101100000001100111111001100010010010011110110011010010010001011011000
Checksum: 1110
Incorrect
Entropy: 01011010000000110011001001001001001110100011100101010001001100111001111111000110000000011011110111011000011001010111001101111100
My checksum: 1010
Iancoleman checksum:1110
第一个成功了,第二个失败了。您可以在下面找到我的功能。
我错过了什么?
def fill_bits(binary, bits):
if len(binary) < bits:
return "0" * (bits - len(binary)) + binary
return binary
# generate a given number of entropy bits
def generate_entropy(bits=256):
if bits < 128 or bits > 256:
raise EntropyRangeExceeded
entropybits = bin(int.from_bytes(os.urandom(bits // 8), byteorder=sys.byteorder))[2:]
return fill_bits(entropybits, bits)
# returns the sha256 hash of the given input
def sha256(_input):
return hashlib.sha256(_input.encode("utf-8")).hexdigest()
# returns the checksum of the input hash
# checksum is given by the first (entropy length / 32)
# bits of the sha256 hash applied on entropy bits
def get_checksum(_entropy):
entropy_length = len(_entropy) // 32
return bin(int(sha256(_entropy), 16))[2:][:entropy_length]
在sha256
中哈希计算错误。可以不进行utf8编码。相反,熵必须表示为字节数组(参见 to_bytes
)并且哈希必须由此生成:
import hashlib
def sha256(_entropy):
entBytes = int(_entropy, 2).to_bytes(len(_entropy) // 8, byteorder='big')
return hashlib.sha256(entBytes).hexdigest()
此外,哈希必须用前导 0 值填充到 256 位的长度(参见 zfill
),以便在校验和中也考虑前导 0 值:
def get_checksum(_entropy):
entropy_length = len(_entropy) // 32
return bin(int(sha256(_entropy), 16))[2:].zfill(256)[:entropy_length];
示例 1,来自 here,第 4 步:
_entropy = '0011001010000101011111010000101111111111101000001001000001001010110100010101111001001011000100111100011110001001111011110111011010010100110011001110111001100010111011010010101101010011110100100110101111110001100101011001000110100010000110110001100101110001'
print(get_checksum(_entropy)) # 11110011
例子2,你的第二个例子:
_entropy = '01011010000000110011001001001001001110100011100101010001001100111001111111000110000000011011110111011000011001010111001101111100'
print(get_checksum(_entropy)) # 1110
示例 3,前导 0 值,与 here 的结果进行比较:
_entropy = '10111101100011110111100011101111111110100010000101111110100101100000001100111111001100010010010011110110011011010010001011011000'
print(get_checksum(_entropy)) # 0010
我有这段代码,将用于根据BIP39 Spec实现助记词生成器。 问题是大多数时候校验和不正确,但在某些情况下它有效,这取决于给定的熵。 (我使用 iancoleman.io bip39 来测试我的校验和)。
观察到以下情况:
使用了 128 位的熵。
Correct
Entropy: 10111101100010110111100011101111111110100010000101111110100101100000001100111111001100010010010011110110011010010010001011011000
Checksum: 1110
Incorrect
Entropy: 01011010000000110011001001001001001110100011100101010001001100111001111111000110000000011011110111011000011001010111001101111100
My checksum: 1010
Iancoleman checksum:1110
第一个成功了,第二个失败了。您可以在下面找到我的功能。
我错过了什么?
def fill_bits(binary, bits):
if len(binary) < bits:
return "0" * (bits - len(binary)) + binary
return binary
# generate a given number of entropy bits
def generate_entropy(bits=256):
if bits < 128 or bits > 256:
raise EntropyRangeExceeded
entropybits = bin(int.from_bytes(os.urandom(bits // 8), byteorder=sys.byteorder))[2:]
return fill_bits(entropybits, bits)
# returns the sha256 hash of the given input
def sha256(_input):
return hashlib.sha256(_input.encode("utf-8")).hexdigest()
# returns the checksum of the input hash
# checksum is given by the first (entropy length / 32)
# bits of the sha256 hash applied on entropy bits
def get_checksum(_entropy):
entropy_length = len(_entropy) // 32
return bin(int(sha256(_entropy), 16))[2:][:entropy_length]
在sha256
中哈希计算错误。可以不进行utf8编码。相反,熵必须表示为字节数组(参见 to_bytes
)并且哈希必须由此生成:
import hashlib
def sha256(_entropy):
entBytes = int(_entropy, 2).to_bytes(len(_entropy) // 8, byteorder='big')
return hashlib.sha256(entBytes).hexdigest()
此外,哈希必须用前导 0 值填充到 256 位的长度(参见 zfill
),以便在校验和中也考虑前导 0 值:
def get_checksum(_entropy):
entropy_length = len(_entropy) // 32
return bin(int(sha256(_entropy), 16))[2:].zfill(256)[:entropy_length];
示例 1,来自 here,第 4 步:
_entropy = '0011001010000101011111010000101111111111101000001001000001001010110100010101111001001011000100111100011110001001111011110111011010010100110011001110111001100010111011010010101101010011110100100110101111110001100101011001000110100010000110110001100101110001'
print(get_checksum(_entropy)) # 11110011
例子2,你的第二个例子:
_entropy = '01011010000000110011001001001001001110100011100101010001001100111001111111000110000000011011110111011000011001010111001101111100'
print(get_checksum(_entropy)) # 1110
示例 3,前导 0 值,与 here 的结果进行比较:
_entropy = '10111101100011110111100011101111111110100010000101111110100101100000001100111111001100010010010011110110011011010010001011011000'
print(get_checksum(_entropy)) # 0010