Тема криптовалют снова начинает будоражить интернет. Супер, что вам не надо идти в отделение банка с паспортом и выстаивать очередь, чтобы открыть счет. Сгенерировать кошелек Bitcoin — дело нескольких строк кода на Python.
Нам понадобятся библиотеки base58 и ecdsa. base58 – это кодирование бинарных данных 58-ю печатными символами (цифрами и латинскими буквами, кроме 0, O, I, l, которые похожи друг на друга). ecdsa – библиотека криптографии на эллиптических кривых.
pip install base58 ecdsa
Импортируем то, что нужно:
import hashlib import ecdsa from binascii import hexlify from base58 import b58encode
Нам нужен приватный ключ, из него мы вычислим публичный ключ, а из него – адрес кошелька Bitcoin. (Обратная процедура не возможна без полного перебора до конца времен). Приватный ключ – это 32 байта данных, которые мы получим из криптографически-надежного источника случайных чисел. Вообще можно придумать свой приватный ключ самостоятельно, если так хочется. Для генерации случайного приватного ключа мы воспользуемся библиотекой ecdsa:
private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
Вычислим этой же библиотекой публичный ключ и добавим спереди байт 0x4 (это признак «несжатого» публичного ключа; есть и другие форматы).
public_key = b'\04' + private_key.get_verifying_key().to_string()
Теперь нужно из публичного ключа сделать привычный число-буквенный адрес Bitcoin. Взглянем на схему:

Для получения адреса из публичного ключа вычисляем сначала RIPEMD160(SHA256(public-key)):
ripemd160 = hashlib.new('ripemd160') ripemd160.update(hashlib.sha256(public_key).digest())
Дополняем его префиксом 0x0 (главная сеть Bitcoin):
r = b'\0' + ripemd160.digest()
Вычисляем контрольную сумму (нужна, чтобы наши денюжки не пропадали, если мы ошибемся в каком-то символе адреса). Контрольная сумма это первые 4 байта от SHA256(SHA256(r)):
checksum = hashlib.sha256(hashlib.sha256(r).digest()).digest()[0:4]
Получаем адрес кошелька, закодировав в base58 сложенные r и checksum:
address = b58encode(r + checksum)
Выведем результат:
print(f'private key: {hexlify(private_key.to_string())}') print(f'public key uncompressed: {hexlify(public_key)}') print(f'btc address: {address}')
Генерация приватного ключа из своего источника случайностей, например, os.urandom:
def random_secret_exponent(curve_order): while True: bytes = os.urandom(32) random_hex = hexlify(bytes) random_int = int(random_hex, 16) if random_int >= 1 and random_int < curve_order: return random_int def generate_private_key(): curve = ecdsa.curves.SECP256k1 se = random_secret_exponent(curve.order) from_secret_exponent = ecdsa.keys.SigningKey.from_secret_exponent return from_secret_exponent(se, curve, hashlib.sha256).to_string()
Важно для конфиденциальных данных, вроде приватного ключа, использовать криптографически безопасный источник случайности. Об этом я писал в одной из недавних статей!
Полный пример кода генерации кошельков.
Проверить ключи и адрес можно здесь. (Нажимаем Skip, дальше Enter my own…)
Подробнее по теме можно почитать здесь.
Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈