Хоть Python из-за медленного интерпритатора не является оптимальным выбором для данной задачи, я разберу генерацию именно на нем.
Для текущей задачи из модулей нам понадобятся:
coincurve — Кроссплатформенные привязки python CFFI для libsecp256k1
pysha3 — оболчка SHA-3 для python (с поддержкой алгоритма keccak)
Генерация адреса в сети Ethereum происходит в 3 этапа:
1. Генерация закрытого ключа
2. Получение открытого ключа из закрытого
3. Получение адреса из открытого ключа
Нужно понимать, что открытый ключ и адрес Etherium — это разные вещи. Адреса — это хэши открытых ключей и отправить средства на открытый ключ невозможно.
Шаг 1: Создаем закрытый ключ
Генерация закрытых ключей происходит с использованием алгоритма хеширования KECCAK-256 . Такая функция генерации случайного 32 байтового начального числа под названием keccak_256 присутствует в модуле pysha3.
import secrets
from sha3 import keccak_256
private_key = keccak_256
Данный алгоритм хоть и является SHA-3, но был немного изменен, прежде чем стать стандартом.
Шаг 2: Получение открытого ключа из закрытого
Чтобы извлечь наш открытй ключ, необходимо подписать ранее сформированный закрытый ключ с помощью алгоритма цифровой подписи на эллиптических кривых (ESCDA). Ethereum использует secp256k1 ECDSA. Наш подключенный модуль coincurve использует его по умолчанию и нам не нужно явно его указывать при вызове.
from coincurve import PublicKey
public_key = PublicKey.from_valid_secret(private_key).format(compressed=False)[1:]
В спецификации к Ethereum указано, что открытый ключ должен быть массивом байтов размером 64.
По умолчанию coincurve использует сжатый формат открытых ключей (libsecp256k1 был разработан для биткойнов, где обычно используются сжатые ключи), размер которого составляет 33 байта. Несжатые ключи имеют размер 65 байт. Кроме того, всем открытым ключам предшествует один байт, чтобы указать, сжаты они или несжаты. Это означает, что нам сначала нужно получить несжатый 65-байтовый ключ ( compressed=False), а затем удалить первый байт ( [1:]), чтобы получить наш 64-байтовый открытый ключ Ethereum.
Шаг 2: Получение адреса из открытого ключа
Теперь мы можем сгенерировать наш адрес Ethereum:
address = keccak_256(public_key).digest()[-20:]
Как указано в спецификации, мы берем самые правые 20 байтов 32-байтового хэша KECCAK соответствующего открытого ключа ECDSA.
Проверим наш код и выведем закрытый ключ и адрес кошелька
print('private_key:', private_key.hex())
print('eth addr: 0x' + addr.hex())