Закрытый ключ, экспортированный из Electrum, не может воссоздать адрес с помощью Python

Я создал новый кошелек Electrum, и вот адрес:

1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA

Щелкнув по нему правой кнопкой мыши, я выбираю «Закрытый ключ», который дает:

Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx

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

Вот что я пробовал:

import bitcoin #pybitcointools
import base58
import binascii

pvt = 'Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx'
pvtdecoded = base58.b58decode(pvt)
pvthex = binascii.hexlify(pvtdecoded)[2:-8]     # remove the first initial byte for version and 4 final bytes for checksum
pvt2 = bitcoin.decode_privkey(pvthex, 'hex')    # decode as a decimal

# generate pubkey from pvtkey with elliptic curve multiplication
public_key = bitcoin.fast_multiply(bitcoin.G, pvt2)
addr = bitcoin.pubkey_to_address(public_key)
print addr

который дает: 1LNSuE4NKHTyHygeKwnU1equ7MjPMhayxBкоторый не является исходным адресом.

В чем дело? Как восстановить исходный адрес ( 1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA) из закрытого ключа с помощью умножения на эллиптическую кривую?


Редактировать : поскольку Kz....Wxзакрытый ключ выглядит как сжатый WIF, я попытался заменить:

pvt2 = bitcoin.decode_privkey(pvthex, 'hex')    # decode as a decimal

к

pvt2 = bitcoin.decode_privkey('Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx', 'wif')

но затем после умножения на эллиптическую кривую он дает другой адрес, который все еще не является хорошим! ( 18dFF3EQoPxR44TygdGxHPMe3LSLFeQe4U)

Примечание: я прочитал en.bitcoin.it/wiki/Wallet_import_format и WIF to private key, но я все еще застрял.

Ответы (2)

В обоих случаях вы не генерируете адрес, соответствующий сжатому открытому ключу.

В первом случае вы создаете недействительный адрес. По крайней мере, закрытый ключ, который он использует, неверен, потому что он имеет байт сжатия. Это изменит значение, которое вы получите для закрытого ключа при его декодировании. Чтобы получить тот же результат, что и во втором случае, вам нужно будет удалить дополнительный байт из декодированного ключа WIF, поскольку этот байт определяет сжатие. Ключ, который вы используете, имеет размер 33 байта, а не 32 байта для реальных закрытых ключей.

Во втором случае вы не создаете сжатый открытый ключ для генерации адреса. Он по-прежнему использует несжатый открытый ключ. Вместо того, чтобы использовать fast_multiplyи создавать открытый ключ самостоятельно, вы должны использовать privkey_to_pubkey. fast_multiplyявляется математической операцией, в ней нет понятия сжатых открытых ключей. Однако privkey_to_pubkeyпри этом он создаст правильный открытый ключ. Затем вы можете использовать этот открытый ключ для генерации адреса.

Вместо того, чтобы делать

public_key = bitcoin.fast_multiply(bitcoin.G, pvt2)

ты должен делать

public_key = bitcoin.privkey_to_pubkey(pvt)
Спасибо за ваш полезный ответ. Что касается вашего последнего абзаца, почему я не могу использовать умножение на эллиптической кривой (такое должно быть под капотом, даже в сжатом случае, верно?)? Также не могли бы вы просто опубликовать (для дальнейшего использования и для уверенности) строку кода, которую мы должны использовать вместо fast_multiply?
Потому что сжатие происходит независимо от операций с эллиптическими кривыми. Операции с эллиптическими кривыми не знают, что такое точечное сжатие; они могут работать только на полной кривой. Однако библиотеки могут использовать точечное сжатие, и это должно происходить отдельно от операций EC.
Спасибо @AndrewChow. Я пробовал с public_key = bitcoin.privkey_to_pubkey(pvt2), но все равно получаю 18dFF3EQoPxR44TygdGxHPMe3LSLFeQe4Uвместо исходного адреса 1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA. Что может быть не так?
Глядя на реализацию этого pybitcointools, вам не нужно декодировать закрытый ключ при использовании privkey_to_pubkey. Скорее, она расшифровывается для вас самой этой функцией. Я обновлю свой ответ правильным кодом.
Большое спасибо! Я изо всех сил пытаюсь получить 1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHAрезультат :)
Вы пробовали последнюю правку?

Основываясь на предложении принятого ответа об использовании privkey_to_pubkey, я проанализировал его код, и это также работает:

pvt = 'Kzuucz58MiTbbedeVuqBaPYwG1TQrV3n2NYU2dJRZ7HEHnHsUXWx'
pvtdecoded = base58.b58decode(pvt)
pvthex = binascii.hexlify(pvtdecoded)[2:-10]     # remove the first initial byte for version and 4 final bytes for checksum
pvt2 = bitcoin.decode_privkey(pvthex, 'hex')     # decode as a decimal

# generate pubkey from pvtkey with elliptic curve multiplication
public_key = bitcoin.fast_multiply(bitcoin.G, pvt2)
public_key = bitcoin.encode_pubkey(public_key, 'hex_compressed')
addr = bitcoin.pubkey_to_address(public_key)
print addr    # 1JkZLnmFfpVFLT2ZMtKzc6BuXMdmY41EHA