Почему btclib.mnemonic_from_raw_entropy утверждает, что я передал ему менее 128 бит энтропии? - PullRequest
1 голос
/ 17 марта 2019

То, что я делаю, - это генерирование «фиктивных» кошельков, извлекая как мнемоническую фразу-пароль, так и кошелек из необработанной энтропии, которая генерируется с использованием secrets.randbits(128) - в результате получается правильная пара ключей bip39.

Ошибка, которую я получаю, такова:

ValueError: 125 bits provided; expected: (128, 160, 192, 224, 256)

Может варьироваться от 122 до 127 бит. Обычно он говорит о том же количестве битов для нескольких ошибок подряд, то есть 125 bits provided 3 раза, затем переключается на 122 bits provided 2 раза, затем работает с 6-й попытки.

Я использую btclib - полная функция

def create_passphrase():
    memo = bip39.mnemonic_from_raw_entropy(secrets.randbits(128) , 'en')

    print(mnemo) 
    return mnemo

Извините, если я упускаю что-то очевидное.

Ответы [ 2 ]

2 голосов
/ 18 марта 2019

Это ошибка в btclib.

Функция bip39.mnemonic_from_raw_entropy() вызывает bip39.entropy_from_raw_entropy(), которая вызывает entropy.str_from_entropy().

Когда entropy.str_from_entropy() вызывается с целым числом в качестве аргумента entr, он пытается преобразовать это целое число в строку, представляющую биты, здесь :

        entr = bin(entr)[2:] # remove '0b'

Это не работает: любое переданное целое число будет, если оно действительно случайным, будет преобразовано только в число битов, ожидаемое примерно в половине времени. Чтобы понять почему, рассмотрим эти примеры случайных данных (для простоты я буду использовать 8 бит, а не 128, но принцип тот же):

>>> bin(0b10001011)[2:]
'10001011'
>>> bin(0b01010110)[2:]
'1010110'
>>> bin(0b00111011)[2:]
'111011'

Как видите, метод преобразования, используемый btclib, удаляет все начальные нули, что приводит к получению строки неправильной длины.

Обходной путь может заключаться в том, чтобы преобразовать результат secrets.randbits(128) в соответствующую строку самостоятельно и передать это:

def create_passphrase(bits=128):
    bitstring = f'{secrets.randbits(bits):0{bits}b}'
    memo = bip39.mnemonic_from_raw_entropy(bitstring , 'en')
    print(memo) 
    return memo

... при условии, что в btclib нет других ошибок, ожидающих вас укусить.

0 голосов
/ 27 апреля 2019

спасибо за отчет.

Потеря ведущих нулей соответствовала энтропии Electrum-> мнемоническому поведению, но привела к ошибке для BIP39.

Теперь исправлено в основной ветке: https://github.com/dginst/btclib/commit/f0f802ef3e31ae74e84964f0ec04d1180f42da27

...