Private key ethereum python

Generating Ethereum Addresses in Python

I’ve been wondering how long it would take to generate all Ethereum private keys with addresses on my laptop.

I know there is not enough energy in our star system to do this in a reasonable timeframe, even on an imaginative computer that would use the absolute minimum of energy possible. This was more of a learning experience for me to get to know more about SHA-3 and KECCAK hashes, ECDSA curves, Public Keys and Ethereum addresses.

Due to its slow interpreter, Python is usually not a good choice when it comes to writing performant applications. The exception being Python modules which use an interface that calls C/C++ code. These modules are usually very fast, popular examples are Tensorflow and Numpy. To generate Ethereum addresses we can use the following two Python modules which are both C based and have a good performance:

  • coincurve: Cross-platform Python CFFI bindings for libsecp256k1
  • pysha3: SHA-3 wrapper for Python (with support for keccak)

Generating Ethereum addresses is a 3-step process:

  1. Generate a private key
  2. Derive the public key from the private key
  3. Derive the Ethereum address from the public key

Note that public keys and Ethereum addresses are not the same. Addresses are hashes of public keys. It’s not possible to send funds to a public key.

Step 1: Generate a private key

Ethereum private keys are based on KECCAK-256 hashes. To generate such a hash we use the keccak_256 function from the pysha3 module on a random 32 byte seed:

Note that a KECCAK hash is not the same as a SHA-3 hash. KECCAK won a competition to become the SHA-3 standard but was slightly modified before it became standardized. Some SHA3 libraries such as pysha3 include the legacy KECCAK algorithm while others, such as the Python hashlib module, only implement the official SHA-3 standard.

Step 2: Derive the public key from the private key

To get our public key we need to sign our private key with an Elliptic Curve Digital Signature Algorithm (ECDSA). Ethereum uses the secp256k1 curve ECDSA. Coincurve uses this as a default so we don’t need to explicitly specify it when calling the function:

The Ethereum Yellow Paper states that the public key has to be a byte array of size 64.

By default coincurve uses the compressed format for public keys (libsecp256k1 was developed for Bitcoin where compressed keys are commonly used) which is 33 bytes in size. Uncompressed keys are 65 bytes in size. Additionally all public keys are prepended with a single byte to indicate if they are compressed or uncompressed. This means we first need to get the uncompressed 65 byte key ( compressed=False ) and then strip the first byte ( [1:] ) to get our 64 byte Ethereum public key.

Step 3: Derive the Ethereum address from the public key

We can now generate our Ethereum address:

As specified in the Yellow Paper we take the right most 20 bytes of the 32 byte KECCAK hash of the corresponding ECDSA public key.

Full Example

This is the full example code from the above steps. It generates a random private key, derives the address and prints them in hex format:

Conclusion

I used the Python timeit module to do a quick benchmark with the above code. The result is that my laptop can generate 18k addresses per second on a single cpu core. Using all 4 cpu cores that’s 72k addresses per second,

6.2 billion (6.220.800.000) addresses per day or around two trillion (2.270.592.000.000) addresses per year.

Ethereum’s address space is 2^160. This means that by using this method it would take my laptop 643665439999999976814879449351716864 (six hundred and forty-three decillion . ) years to generate all Ethereum private keys with addresses.

Источник

Private key ethereum python

Ethereum Private Key Brute Force Attacker

A simple, pure-python script to generate private keys and compare the resulting ETH addresses with a list of known values. Strength of each guess is measured by the number of leading hexadecimal digits that match (other digits may match, but we don’t count those).

While guessing, the script shows its guesses WarGames-style.

Thanks to @vkobel/ethereum-generate-wallet for the pure-python implementation of ETH key generation.

I wanted a more tangible understanding of how hard it is to guess a private key before using it to store any non-trivial value. I mean, how hard could it be to guess someone else’s key, right? As this script tries to show, it’s basically impossible to collide with an already existing key.

How many leading digits can you match? 😉

Note: having a 39 digit match of the address means you’re no closer to unlocking anything.

Seriously, no chance

How impossible is this? Assuming 45,000,000 addresses, you have a 45000000 / 115792089237316195423570985008687907853269984665640564039457584007913129639936 or 3.8862758497925e-70 chance of randomly guessing a private key associated with a public address.

If you made O(100) random guesses per second, it would take you on roughly 1 trillion trillion trillion trillion years to guess one address (on average). Clearly a short-cut is needed, but that’s for another project.

This script uses python3. Its dependencies are listed in requirements.txt . Use virtualenv to install and execute this script without affecting your system’s python3 distribution:

Not recommended: you can skip the virtualenv steps and install the necessary dependencies to your system’s python3 distribution:

libyaml is not found

Your python development environment is missing a few components. Ensure you have libyaml-dev , libpython3-dev , and python3-dev installed.

Читайте также:  Средневзвешенная доходность внутренняя доходность портфеля

Click wants UTF-8 but your python install was configured for ASCII

Export the recommended locale information to make click happy.

If you specify a —port command line argument, the app listens on that port for HTTP GETs and will return some basic run-time statistics.

About

Brute force private key attack against ethereum wallets

Источник

Private key ethereum python

A common API for Ethereum key operations with pluggable backends.

This library and repository was previously located at https://github.com/pipermerriam/ethereum-keys. It was transferred to the Ethereum foundation github in November 2017 and renamed to eth-keys . The PyPi package was also renamed from ethereum-keys to eth-keys .

Running the tests

You can run the tests with:

Or you can install tox to run the full test suite.

Pandoc is required for transforming the markdown README to the proper format to render correctly on pypi.

For Debian-like systems:

To release a new version:

How to bumpversion

The version format for this repo is .. for stable, and ... for unstable ( stage can be alpha or beta).

To issue the next version in line, specify which part to bump, like make release bump=minor or make release bump=devnum .

If you are in a beta version, make release bump=stage will switch to a stable.

To issue an unstable version when the current version is stable, specify the new version explicitly, like make release bump=»—new-version 2.0.0-alpha.1 devnum»

The KeyAPI object is the primary API for interacting with the eth-keys libary. The object takes a single optional argument in its constructor which designates what backend will be used for eliptical curve cryptography operations. The built-in backends are:

  • eth_keys.backends.NativeECCBackend : A pure python implementation of the ECC operations.
  • eth_keys.backends.CoinCurveECCBackend : Uses the coincurve library for ECC operations.

By default, eth-keys will try to use the CoinCurveECCBackend , falling back to the NativeECCBackend if the coincurve library is not available.

Note: The coincurve library is not automatically installed with eth-keys and must be installed separately.

The backend argument can be given in any of the following forms.

  • Instance of the backend class
  • The backend class
  • String with the dot-separated import path for the backend class.

The backend can also be configured using the environment variable ECC_BACKEND_CLASS which should be set to the dot-separated python import path to the desired backend.

KeyAPI.ecdsa_sign(message_hash, private_key) -> Signature

This method returns a signature for the given message_hash , signed by the provided private_key .

  • message_hash : must be a byte string of length 32
  • private_key : must be an instance of PrivateKey

KeyAPI.ecdsa_verify(message_hash, signature, public_key) -> bool

Returns True or False based on whether the provided signature is a valid signature for the provided message_hash and public_key .

  • message_hash : must be a byte string of length 32
  • signature : must be an instance of Signature
  • public_key : must be an instance of PublicKey

KeyAPI.ecdsa_recover(message_hash, signature) -> PublicKey

Returns the PublicKey instances recovered from the given signature and message_hash .

  • message_hash : must be a byte string of length 32
  • signature : must be an instance of Signature

Returns the PublicKey instances computed from the given private_key instance.

  • private_key : must be an instance of PublicKey

Common APIs for PublicKey , PrivateKey and Signature

There is a common API for the following objects.

Each of these objects has all of the following APIs.

  • obj.to_bytes() : Returns the object in it’s canonical bytes serialization.
  • obj.to_hex() : Returns a text string of the hex encoded canonical representation.

The PublicKey class takes a single argument which must be a bytes string with length 64.

Note that there are two other common formats for public keys: 65 bytes with a leading \x04 byte and 33 bytes starting with either \x02 or \x03 . To use the former with the PublicKey object, remove the first byte. For the latter, refer to PublicKey.from_compressed_bytes .

The following methods are available:

This classmethod returns a new PublicKey instance computed from its compressed representation.

  • compressed_bytes must be a byte string of length 33 starting with \x02 or \x03 .

This classmethod returns a new PublicKey instance computed from the given private_key .

  • private_key may either be a byte string of length 32 or an instance of the KeyAPI.PrivateKey class.

PublicKey.recover_from_msg(message, signature) -> PublicKey

This classmethod returns a new PublicKey instance computed from the provided message and signature .

  • message must be a byte string
  • signature must be an instance of KeyAPI.Signature

PublicKey.recover_from_msg_hash(message_hash, signature) -> PublicKey

Same as PublicKey.recover_from_msg except that message_hash should be the Keccak hash of the message .

PublicKey.verify_msg(message, signature) -> bool

This method returns True or False based on whether the signature is a valid for the given message.

PublicKey.verify_msg_hash(message_hash, signature) -> bool

Same as PublicKey.verify_msg except that message_hash should be the Keccak hash of the message .

Returns the compressed representation of this public key.

Returns the hex encoded ethereum address for this public key.

Returns the ERC55 checksum formatted ethereum address for this public key.

Returns the 20-byte representation of the ethereum address for this public key.

The PrivateKey class takes a single argument which must be a bytes string with length 32.

The following methods and properties are available

This property holds the PublicKey instance coresponding to this private key.

This method returns a signature for the given message in the form of a Signature instance

  • message must be a byte string.

Same as PrivateKey.sign except that message_hash should be the Keccak hash of the message .

The Signature class can be instantiated in one of two ways.

  • signature_bytes : a bytes string with length 65.
  • vrs : a 3-tuple composed of the integers v , r , and s .

Note: If using the signature_bytes to instantiate, the byte string should be encoded as r_bytes | s_bytes | v_bytes where | represents concatenation. r_bytes and s_bytes should be 32 bytes in length. v_bytes should be a single byte \x00 or \x01 .

Signatures are expected to use 1 or 0 for their v value.

Читайте также:  Многопроцессорные материнские платы майнинг

The following methods and properties are available

This property returns the v value from the signature as an integer.

This property returns the r value from the signature as an integer.

This property returns the s value from the signature as an integer.

This property returns a 3-tuple of (v, r, s) .

Signature.verify_msg(message, public_key) -> bool

This method returns True or False based on whether the signature is a valid for the given public key.

  • message : must be a byte string.
  • public_key : must be an instance of PublicKey

Signature.verify_msg_hash(message_hash, public_key) -> bool

Same as Signature.verify_msg except that message_hash should be the Keccak hash of the message .

This method returns a PublicKey instance recovered from the signature.

  • message : must be a byte string.

Same as Signature.recover_public_key_from_msg except that message_hash should be the Keccak hash of the message .

This error is raised during instantaition of any of the PublicKey , PrivateKey or Signature classes if their constructor parameters are invalid.

This error is raised from any of the recover or verify methods involving signatures if the signature is invalid.

Источник

Сетевой протокол Ethereum с нуля. Часть первая. Соединение

В этой статье мы разберемся в основных концепциях работы сети Ethereum и напишем Python-скрипт для ее пингования.

Ethereum — это криптовалюта, где код может исполняться посредством блокчейна. Эта возможность позволяет создавать «умные контракты», которые будут выполняться автоматически. Давайте разберемся, как работают «умные контракты» и протокол Ethereum в целом.

Предполагается, что у читателя есть базовое понимание Python, Git и сетевых концепций, таких как TCP и UDP.

Концепция криптовалюты

Под криптовалютой подразумевается механизм, который использует децентрализованное хранение и передачу информации. В централизованных системах всегда есть доверенная третья сторона, которая отслеживает все учетные данные и занимается обработкой транзакций. Без посредника сторонам может быть трудно доказать, что то, о чем они говорят, действительно принадлежит им. Такую систему использует большинство банков мира.

Криптовалюты решают проблему децентрализованного регулирования, так как каждый элемент сети ведет учет всех проходящих в ней транзакций. Для поддержания консенсуса после проведения транзакции данные о ней передаются в сеть вместе с математической задачей, которую решают узлы сети и распространяют далее. Это обновление, протекающее по сети, и является доказательством того, что транзакция была проведена успешно и имеет место быть.

Настройка среды разработки

Все нижеприведенные действия производились на Amazon Linux и должны быть осуществимы на OS X и большинстве дистрибудивов Linux.

Intel , Нижний Новгород, можно удалённо , По итогам собеседования

Давайте создадим виртуальную среду для этого проекта:

Виртуальная среда не позволит произойти конфликту модулей Python.

Для активации виртуального окружения запустите команду:

Это приведет к изменению некоторых переменных среды. Теперь Python будет использовать пакеты только из виртуальной среды, pip будет ставить пакеты только туда.

Вы можете убедиться, что все сработало, проверив путь к среде:

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

Это довольно удобно использовать при работе над проектом.

Примечание Используемая версия Python 2.7.12 не гарантирует, что все будет работать с другим версиями.

Версию можно проверить командой:

Последнее, что нужно сделать — создать пакетный скелет с библиотекой pipiecutter:

Будем использовать minimal skeleton , который позволяет производить публикацию в pip и выполнять тестирование:

Вам потребуется ответить на некоторые вопросы для настройки проекта. Назовем проект pyethtutorial . После этого вы можете настроить Git для его отслеживания.

Также давайте установим пакет nose . Он понадобится для тестирования:

Теперь давайте проверим, что все работает. В pyethtutorial/tests есть один тест, который поможет нам в этом убедиться:

Для запуска всех тестов используйте команду nosetests в каталоге проекта:

Все работает. Идем дальше.

Реализация

Нам нужно выяснить, как общаться с другими узлами сети.
Вот отрывок из документации по протоколу Ethereum:

Одноранговая связь между узлами, на которых запущенны клиенты Ethereum, выполняется с использованием протокола devp2p.

Узлы devp2p обмениваются сообщениями с использованием RLPx — транспортного протокола, использующего шифрование. Одноранговые узлы могут предлагать и принимать соединения на любых TCP-портах, однако по умолчанию порт, на котором может быть установлено соединение, будет 30303.

Узлы devp2p находят соседние узлы с помощью протокола обнаружения DHT.

Таким образом по умолчанию мы отправляем пакеты через порт 30303, используя протокол RLPx. Протокол devp2p имеет два разных режима: основной, который использует TCP, и режим обнаружения, который использует UDP. UDP работает таким образом: вы подключаетесь к определенным серверам, называемыми «узлами начальной загрузки» (для BitTorrent это router.bittorrent.com и router.utorrent.com), которые предоставляют вам небольшой список одноранговых узлов для подключения. После получения списка узлов вы можете подключиться к ним. Сервера в свою очередь будут делиться своими списками узлов с вами. Это будет продолжаться до тех пор, пока у вас не будет полного списка узлов в сети.

Звучит достаточно просто, но давайте сделаем это еще проще. В спецификации RLPx есть раздел «Обнаружение узла». В нем описано, как сообщения отправляются через UPD порт 30303, задавая следующую структуру пакетов:

И различные типы пакетов:

Типы сообщений представлены C-подобными структурами данных. Самое простое, что мы можем сделать сейчас — это реализовать пакет PingNode , который состоит из объекта version , двух объектов EndPoint и timestamp . Объекты EndPoint состоят из IP-адреса и двух целых чисел, представляющих порты UDP и TCP соответственно.

Чтобы отправить пакеты на аппаратный интерфейс, они кодируются по стандарту RLP. В документации говорится:

Функция кодирования RLP принимает элемент. Элемент определяется следующим образом:
Строка (то есть массив байтов) является элементом.
Список элементов — это элемент.

Кодирование RLP определяется следующим образом:
Для одного байта, значение которого находится в диапазоне [0x00, 0x7f], этот байт является его собственной RLP-кодировкой.
В противном случае, если длина строки составляет 0-55 байт, кодировка RLP состоит из одного байта со значением 0x80 плюс длина строки, за которой следует строка. Таким образом, диапазон первого байта [0x80, 0xb7].
Если длина строки больше 55 байтов, то RLP-кодировка состоит из одного байта со значением 0xb7 плюс длина в строки в двоичной форме, за которой следует длина строки, за которой следует строка. Например, строка длиной 1024 будет кодироваться как \ xb9 \ x04 \ x00, за которой следует строка. Таким образом, диапазон первого байта равен [0xb8, 0xbf].
Если общая полезная нагрузка списка (т. е. длина всех элементов) составляет 0-55 байт, то RLP-кодирование состоит из одного байта со значением 0xc0 плюс длина списка, за которым следует последовательность RLP-кодировок каждого элемента. Таким образом, диапазон первого байта [0xc0, 0xf7].
Если общая полезная нагрузка списка составляет более 55 байтов, то RLP-кодирование состоит из одного байта со значением 0xf7 плюс длина полезной нагрузки в двоичной форме, за которой следует длина полезной нагрузки, за которой следует последовательность RLP-кодировок объектов. Таким образом, диапазон первого байта [0xf8, 0xff].

Читайте также:  Pny quadro gv100 майнинг

Прежде чем что-либо можно будет закодировать в RLP, нужно преобразовать структуру в «элемент»: либо строку, либо список элементов (определение является рекурсивным). Как сказано в документации, RLP просто кодирует «структуру» и оставляет интерпретацию байтов содержимого протоколу более высокого порядка.

Начнем реализацию самого протокола. Будем использовать библиотеку rlp для RLP-кодирования и декодирования. Для установки используем pip install rlp .

У нас есть все необходимое для отправки пакета PingNode . Далее мы создадим PingNode , упакуем его и отправим. Чтобы упаковать данные, мы начнем с RLP-кодирования структуры, потом добавим байт, чтобы обозначить тип структуры, добавим криптографическую подпись и, наконец, добавим хеш для проверки целостности пакета. Приступим.

Первый класс — это класс EndPoint . Ожидается, что порты будут целыми числами и адрес будет находиться в формате 127.0.0.1. Адрес передается в библиотеку ipaddress , поэтому мы можем использовать его служебные функции, например, преобразование представления с точками в двоичный формат, что и происходит в методе pack . Для установки этого пакета используйте pip install ipaddress . Метод pack подготавливает объект, который будет использоваться rlp.encode , преобразуя его в список строк. Для портов на странице спецификации RLP сказано: «Целые числа Ethereum должны быть представлены в бинарной форме», а спецификация Endpoint перечисляет их типы данных как uint16_t или беззнаковые 16-битные целые числа. Таким образом, используется метод struck.pack с строкой формата >H , что означает «big-endian unsigned 16-bit integer».

Следующий класс — это PingNode . Вместо того, чтобы задавать значения позже, введем исходные байтовые значения для packet_type и version . Для метода pack мы можем использовать исходное значение версии, так как оно уже находится в байтах. Для адресов будем использовать struct.pack со строкой формата >I . Также добавим 60 к отметке времени, чтобы дать дополнительные 60 секунд и пакет успел прибыть в пункт назначения. (В документации сказано, что пакеты с устаревшей временной меткой не обрабатываются.)

Последний класс — PingServer . Этот класс открывает сокеты, подписывает, хеширует сообщения и отправляет их на другие серверы. Конструктор принимает объект EndPoint . Далее при создании сервера загружается секретный ключ, который мы должны инициализировать.

Ethreum использует систему асимметричного шифрования, основанную на эллиптических кривых secp256k1 . Для реализации понадобится библиотека secp256k1-py . Установим pip install secp256k1 .

Чтобы сгенерировать ключ, вызовем конструктор Private Key с None в качестве аргумента, а затем запишем вывод функции serialized() в файл:

Помещаем файл в каталог с проектом. Не забудьте добавить его в .gitignore , если вы используете Git, чтобы случайно его не опубликовать.

Метод wrap_packet кодирует пакет: hash || signature || packet-type || packet-data

Первое, что нужно сделать, — добавить тип пакета в RLP-код пакетных данных. Затем хэшированная полезная нагрузка подписывается с помощью функции ecdsa_sign_recoverable и ключа. Параметр raw установлен в значение True , потому что мы сами сделали хеширование (иначе функция использовала бы собственную хеш-функцию). Затем мы обрабатываем подпись и добавляем ее перед полезной нагрузкой. Наконец, вся полезная нагрузка хэшируется, и этот хэш добавляется в пакет. Теперь пакет готов к отправке.

Возможно, вы заметили, что мы еще не определили функцию keccak256 . Ethereum использует нестандартный алгоритм sha3 , называемый keccak-256 . Библиотека pysha3 реализует ее. Используйте pip install pysha3 для установки.

В pyethtutorial/crypto.py мы определяем keccak256 :

Вернемся к PingServer . Следующая функция udp_listen обрабатывает входящие передачи. Она создает объект сокета, который привязывается к UDP-порту сервера. Затем определяется функция receive_ping , которая принимает входящие данные, выводит их и возвращает объект Thread , который будет запускать get_ping , поэтому мы можем отправлять пинги одновременно с приемом входящих данных.

Последний метод ping создает объект PingNode , формирует сообщение с помощью wrap_packet и отправляет его с использованием UDP.

Теперь мы можем настроить скрипт, который будет отправлять некоторые пакеты.

Запустим код и получим следующий вывод:

Мы успешно запинговали самих себя.

Пытаемся пинговать соседний узел

Хорошими кандидатами для приема наших сообщений будут те самые узлы начальной загрузки. В документации сказано:

Чтобы начать работу, geth использует узлы начальной загрузки, адреса которых записаны в исходном коде.

Geth — это Ethereum-клиент, реализованный на Go. В этом репозитории файл /bootnodes.go содержит списки узлов начальной загрузки в специальном формате:

Ниже перечислены основные узлы сети:

Для примера используется узел US-WEST, но вы можете использовать любой из этого списка. Например, ближайший к вам.

Сейчас send_ping.py выглядит так:

Давайте проверим, что выйдет:

Ждет ответа, но его нет. Разберемся, что пошло не так.

Решение

Оказывается, что Ethereum использует адрес возврата из заголовка UPD, а не тот, который мы ему передаем в PingNode .

53042 — это порт из заголовка UDP. Сокет отправляет пакет с этим заголовком, потому что он не привязан к какому-либо порту заранее. Ниже в комментариях отмечены проблемы с PingServer :

Проблема в том, что udp_listen и ping используют разные сокеты (созданные на строках 3 и 15), а тот, который используется ping , не привязан к порту 30303, поэтому он использует произвольный порт.

Чтобы исправить это, нужно переопределить порт в методе __init__ на сервере. Окончательный результат выглядит примерно так:

Сокет инициализирован в __init__ и указан в udp_listen и ping .

Теперь попробуем запустить send_ping.py :

Мы получили сообщение от узла начальной загрузки! Отлично.

Источник

Оцените статью