BIP39 Контрольная сумма иногда не срабатывает - PullRequest
1 голос
/ 04 мая 2020

У меня есть этот фрагмент кода, который будет использоваться для реализации генератора фраз мнемони c в соответствии с BIP39 Spe c. Проблема в том, что в большинстве случаев контрольная сумма неверна, но в некоторых случаях она работает, это зависит от заданной энтропии. (Я использовал 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]

1 Ответ

1 голос
/ 05 мая 2020

В sha256 га sh рассчитан неверно. Кодировка Utf8 не может быть выполнена. Вместо этого энтропия должна быть представлена ​​в виде байтового массива (см. to_bytes), и га sh должен быть сгенерирован из этого:

import hashlib
def sha256(_entropy):
    entBytes = int(_entropy, 2).to_bytes(len(_entropy) // 8, byteorder='big')
    return hashlib.sha256(entBytes).hexdigest()

Кроме того, ха sh должен быть дополнен начальным От 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, с здесь, шаг 4:

_entropy = '0011001010000101011111010000101111111111101000001001000001001010110100010101111001001011000100111100011110001001111011110111011010010100110011001110111001100010111011010010101101010011110100100110101111110001100101011001000110100010000110110001100101110001'
print(get_checksum(_entropy)) # 11110011

Пример 2, ваш второй пример:

_entropy = '01011010000000110011001001001001001110100011100101010001001100111001111111000110000000011011110111011000011001010111001101111100'
print(get_checksum(_entropy)) # 1110

Пример 3, ведущие 0-значения, сравните с результатом из здесь :

_entropy = '10111101100011110111100011101111111110100010000101111110100101100000001100111111001100010010010011110110011011010010001011011000'
print(get_checksum(_entropy)) # 0010
...