Каким критериям должен соответствовать действующий адрес Ethereum? Это просто случайное число в шестнадцатеричном формате? Или его нужно выводить особым образом, в соответствии с какими-то криптографическими алгоритмами? Какие алгоритмы и стандарты используются для генерации пары ключей?
Недавно мое внимание привлекла эта статья, которая намного более глубокая и техническая, чем моя более доступная версия ниже. Он также расскажет вам, как создать его самостоятельно. Я настоятельно рекомендую это: https://kobl.one/blog/create-full-ethereum-keypair-and-address/
Создайте случайный закрытый ключ (64 (шестнадцатеричных) символа / 256 бит / 32 байта)
Получите открытый ключ из этого закрытого ключа (128 (шестнадцатеричных) символов / 512 бит / 64 байта)
Получите адрес из этого открытого ключа. (40 (шестнадцатеричных) символов / 160 бит / 20 байт)
Несмотря на то, что многие люди называют адрес открытым ключом, на самом деле в Ethereum это не так. Существует отдельный открытый ключ, выступающий в роли посредника, которого вы никогда не увидите, если только не покопаетесь в JSON-файле предпродажного кошелька.
Закрытый ключ состоит из 64 шестнадцатеричных символов. Каждая отдельная строка из 64 шестнадцатеричных символов гипотетически является закрытым ключом Ethereum (см. ссылку вверху, почему это не совсем точно) , который будет получать доступ к учетной записи. Если вы планируете создать новую учетную запись, вы должны быть уверены, что для них задан правильный генератор случайных чисел. Как только у вас есть эта строка..
Это тяжело и выше моего понимания. Есть что-то с алгоритмом цифровой подписи на эллиптических кривых (ECDSA) и прочим. Но в итоге вы получите открытый ключ размером 64 байта.
Начните с открытого ключа (128 символов / 64 байта)
Возьмите хэш открытого ключа Keccak-256. Теперь у вас должна быть строка размером 64 символа / 32 байта. (примечание: SHA3-256 со временем стал стандартом, но Ethereum использует Keccak)
Возьмите последние 40 символов/20 байт этого открытого ключа (Keccak-256). Или, другими словами, отбросить первые 24 символа/12 байт. Эти 40 символов / 20 байт и есть адрес. С префиксом 0x он становится длиной 42 символа.
Адрес: адрес Ethereum представляет учетную запись. Для EOA адрес определяется как последние 20 байтов открытого ключа, управляющего учетной записью, например, `cd2a3d9f938e13cd947ec05abc7fe734df8dd826. Это шестнадцатеричный формат (с основанием 16), который часто указывается явно добавлением 0x к адресу. Web3.js и консольные функции принимают адреса с этим префиксом или без него, но для прозрачности мы поощряем их использование. Поскольку каждый байт адреса представлен двумя шестнадцатеричными символами, адрес с префиксом имеет длину 42 символа. Несколько приложений и API также предназначены для реализации новой адресной схемы с поддержкой контрольной суммы, представленной в кошельке Mist Ethereum с версии 0.5.0. - Документы усадьбы
Закрытый ключ: произвольно выбранное положительное целое число (представленное в виде массива байтов длиной 32 в форме с обратным порядком байтов) в диапазоне [1, secp256k1n − 1]
. - Желтая бумага
Пространство для закрытого ключа:
Вот несколько примеров кода, основанных на эллиптической кривой secp256k1, используемой Эфириумом n
. быть записано в шестнадцатеричном формате как:0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
Проверка ошибок:
Различные библиотеки будут выдавать ошибки, если вы попытаетесь ввести в них закрытый ключ, превышающий n
, в качестве механизма проверки ошибок (т . Е. Exception: Invalid privkey
). См. этот связанный ответ с примерами для более подробной информации.
Связанные параметры кривой:
Мы можем назвать закрытый ключ s
, чтобы обозначить его как секретную экспоненту, так как это значение огибает кривую с помощью параметра g
(с использованием скалярного умножения), который обозначает общедоступную точку генератора, которая похожа на универсальную константу, которую все знают и используют, чтобы сгенерировать свой открытый ключ из s
.
So g
остается общедоступным, но s
должен храниться в секрете, чтобы кошелек ethereum оставался безопасным после получения вашего адреса ethereum из вашего открытого ключа.
Открытый ключ может быть представлен либо в сжатом формате общей длиной 33 байта, либо в несжатом формате длиной 64 байта, и обычно обозначается начальным префиксом 0x02 для сжатых открытых ключей, но длина строки является лучшим индикатором, поскольку префикс также не видны или не присутствуют в зависимости от шага и реализации.
Вывод криптографически безопасного ключа:
Выбранный способ s
также имеет огромное значение с точки зрения его криптографической безопасности. Другими словами, не рекомендуется выбирать этот секретный показатель самостоятельно или придумывать какой-либо умный метод, как вы могли бы для пароля (также известного как мозговой кошелек), поскольку бесчисленное количество таких методов использовалось в течение десятилетий для взлома секретов с использованием различных алгоритмов и компьютерное программное обеспечение, например, используемое для взлома паролей.
Следовательно, секретный показатель должен быть сгенерирован с использованием криптографически безопасного генератора псевдослучайных чисел (CSPRNG), такого как криптографический API консорциума WorldWideWeb (W3C) ( раскрытие информации: я являюсь одним из 12 участников этой спецификации на Github ), так что гораздо менее вероятно, что злоумышленник сможет предсказать это значение, поскольку случайные биты, составляющие это число, поступают из разных мест с вашего локального устройства и из процессов, которые не передают эти данные энтропии онлайн (при условии, что программное обеспечение, которое вы используют безопасно вместе с безопасным CSPRNG).
Пример кода Python:
Используя Python 3, в библиотеке секретов есть CSPRNG, который может быть таким же простым, как запуск следующих команд по порядку из интерпретатора IDLE или файла .py после импорта библиотеки секретов:
secrets.randbits(256)
Приведенная выше команда создаст 256-битное двоичное число, которое можно использовать в качестве закрытого ключа, если оно меньше значения n
, но его необходимо отформатировать как байтовый объект в приведенном ниже примере реализации Python с использованием eth-keys
библиотеки из пакета Репозиторий Ethereum Foundation Github (в приведенном ниже примере может потребоваться установка sha3
библиотеки ( pip install pysha3 ), которая содержит Keccak, если ее нет в hashlib
библиотеке по умолчанию):
import secrets
import sha3
import eth_keys
from eth_keys import keys
private_key = str(hex(secrets.randbits(256))[2:])
private_key_bytes = bytes.fromhex(private_key)
public_key_hex = keys.PrivateKey(private_key_bytes).public_key
public_key_bytes = bytes.fromhex(str(public_key_hex)[2:])
Keccak256_of_public_key_bytes = sha3.keccak_256(public_key_bytes).hexdigest()
public_address = keys.PublicKey(public_key_bytes).to_address()
print('\n Private_key:',private_key,
'\n Private_key_bytes:',private_key_bytes,
'\n Public_key_hex:',public_key_hex,
'\n Public_key_bytes:',public_key_bytes,
'\n Full_Keccak_digest:',Keccak256_of_public_key_bytes,
'\n Ethereum address:',public_address)
Пример вывода приведенного выше кода (не для использования в основной сети, например)
Private_key: 7231bfb75a41481965e391fb6d4406b6c356d20194c5a88935151f05136d2f2e
Private_key_bytes: b'r1\xbf\xb7ZAH\x19e\xe3\x91\xfbmD\x06\xb6\xc3V\xd2\x01\x94\xc5\xa8\x895\x15\x1f\x05\x13m/.'
Public_key_hex: 0x013e81c4a44c5303b11452f649be9427b75605339d8eba90f8e99cc401a8bd4f7494e0d0740bcc0282af75f9bd4571ed493a05ed02f1b968a45a46f4d77be149
Public_key_bytes: b"\x01>\x81\xc4\xa4LS\x03\xb1\x14R\xf6I\xbe\x94'\xb7V\x053\x9d\x8e\xba\x90\xf8\xe9\x9c\xc4\x01\xa8\xbdOt\x94\xe0\xd0t\x0b\xcc\x02\x82\xafu\xf9\xbdEq\xedI:\x05\xed\x02\xf1\xb9h\xa4ZF\xf4\xd7{\xe1I"
Full_Keccak_digest: 3f54dd68163875b594cfdc8e8a2250aafb31638b19a83caa49d1ee61089dcb4b
Ethereum address: 0x8a2250aafb31638b19a83caa49d1ee61089dcb4b
Шесть шагов от закрытого ключа до адреса Ethereum
Как видно из вышеприведенной реализации, которую я написал, шесть шагов перехода от закрытого ключа к адресу ethereum можно обобщить следующим образом:
Альтернативные зависимости:
В дополнение к библиотеке open-ssl, упомянутой в статье, которую отметил @tayvano, другие библиотеки, которые можно использовать для вычисления общедоступных адресов эллиптических кривых, включают библиотеку ecdsa Python и библиотеку биткойнов secp256k1, написанную на C , хотя последняя будет содержать инструменты для форматирования . биткойн-адреса, которые полностью отличаются от адресов ethereum из-за этапов форматирования и различных алгоритмов хеширования и методов кодирования, даже если базовый закрытый ключ и открытый ключ совпадают, например.
Примечание. Наконец, важно иметь тесты, чтобы убедиться, что сгенерированный адрес не только действителен, но и что базовый закрытый ключ, используемый в процессе, будет действителен для подписи транзакций (т. е. если пользователь создает хеш-дайджест адреса). массив байтов, рассматриваемый как строка вместо объекта байтов, что приведет к неправильному хеш-дайджесту и, следовательно, к неправильному адресу для базового ключа).
Пример : Одним из таких инструментов проверки адреса (контрольной суммы) из библиотеки eth-keys является следующая команда: keys.PublicKey().to_checksum_address()
которая использует байты открытого ключа (т. е. передача переменной public_key_bytes
в первую скобку будет выглядеть так в приведенной выше программе keys.PublicKey(public_key_bytes).to_checksum_address()
, чтобы убедиться, что вычисленный адрес правильный). Вот почему использование существующих библиотек может быть безопаснее, чем писать код с нуля.
PS Ответы и примеры не претендуют на полноту всех рисков/шагов.
n
, см.: eips.ethereum.org/EIPS/eip-1271 : «Если ваша библиотека генерирует податливые подписи, такие как s
-значения в верхнем диапазоне, рассчитайте новое s-значение с 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1
и перевернуть v
с 27
на 28
или наоборот. Если ваша библиотека также генерирует подписи с помощью 0
/ 1
for v
вместо 27
/ 28
, добавьте 27
, чтобы v
также принимать эти податливые подписи».Адреса Ethereum — это хэши открытого ключа. Таким образом, чтобы сгенерировать его, вы должны сначала сгенерировать закрытый ключ (см.: Каков подход к вычислению адреса Ethereum из 256-битного закрытого ключа? ) Закрытый ключ является случайным, но открытый ключ и, следовательно, его хеш, используемый в качестве адреса, не случайно.
Чтобы проверить адрес и, таким образом, узнать его формат, обратитесь к разделу Как проверить, действителен ли адрес Ethereum?
Если кто-то ищет решение JS:
const Web3 = require('web3')
const web3 = new Web3()
const elliptic = require('elliptic')
const ec = new elliptic.ec('secp256k1')
function pubKeyToAddress(compressedPubkey) {
let keyPair = ec.keyFromPublic(compressedPubkey, 'hex')
// remove '04' then add prefix '0x'
let pubkey = '0x' + keyPair.getPublic(false, 'hex').substr(2)
let address = trimFirst12Bytes(web3.utils.keccak256(pubkey))
return web3.utils.toChecksumAddress(address)
}
unction trimFirst12Bytes(hexString) {
return '0x'.concat(hexString.substr(hexString.length - 40))
}
Вот пакет Python, размещенный в PyPI: eth_address_dump
Дамп eth-адреса из закрытого ключа:
$ echo "0x6ee825aafad19a0d759e1e0ba61d0c523b7b23038998a92d7904458b91667105" | eth_address_dump
private_key = 0x6ee825aafad19a0d759e1e0ba61d0c523b7b23038998a92d7904458b91667105
public_key = 0xaa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9fe85fc162e43d721533736d79c102139d3035d2d9251ccf809bc5bddb81cc6563
compressed_public_key = 0x03aa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9f
address = 0xF7dcf60AebA077461862d51b77d6d804C06E0073
Дамп eth-адреса из мнемонических слов:
$ echo "olympic wine chicken argue unaware bundle tunnel grid spider slot spell need" | eth_address_dump
mnemonic = olympic wine chicken argue unaware bundle tunnel grid spider slot spell need
private_key = 0x6ee825aafad19a0d759e1e0ba61d0c523b7b23038998a92d7904458b91667105
public_key = 0xaa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9fe85fc162e43d721533736d79c102139d3035d2d9251ccf809bc5bddb81cc6563
compressed_public_key = 0x03aa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9f
address = 0xF7dcf60AebA077461862d51b77d6d804C06E0073
Дамп eth-адреса из сжатого открытого ключа:
$ echo "0x03aa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9f" | eth_address_dump
public_key = 0xaa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9fe85fc162e43d721533736d79c102139d3035d2d9251ccf809bc5bddb81cc6563
compressed_public_key = 0x03aa3e0b3f86053c2aaa08d6f6398e18f76100e0d675680228b000c252e4393e9f
address = 0xF7dcf60AebA077461862d51b77d6d804C06E0073
Сначала генерируется случайный закрытый ключ из 64 (шестнадцатеричных) символов (256 бит / 32 байта).
Затем из сгенерированного закрытого ключа получается открытый ключ из 128 (шестнадцатеричных) символов (512 бит / 64 байта) с использованием алгоритма цифровой подписи на основе эллиптических кривых ( ECDSA ).
Затем к открытому ключу применяется хэш-функция Keccak-256 для получения хэш-строки из 64 символов (256 бит / 32 байта). Последние 40 символов этой строки с префиксом 0x становятся окончательным адресом Ethereum. (Примечание: 0x в кодировке означает, что число/строка записаны в шестнадцатеричном формате.)
Примечание. Более подробное, но простое математическое объяснение этих шагов можно найти в этой очень полезной статье . Если вы хотите глубже погрузиться в концепцию, прочтите эту книгу .
Пример простого кода Python с использованием модуля eth_account
from eth_account import Account
acc = Account.create(password_string)
prv = acc.key
pub = Account._parsePrivateKey(prv).public_key
addr = acc.address
Николя Массар
Николя Массар
q9f
Паула Ливингстон