Я понимаю концепцию высокого уровня, меня больше интересуют конкретные детали. Как генерируется закрытый ключ. Как именно генерируется открытый ключ, как генерируется адрес из открытого ключа.
Открытый и закрытый ключи в биткойн-адресе представляют собой обычную пару ключей ECDSA . Я не копался в этом конкретном фрагменте собственного кода Биткойн, но ответвления продуктов, с которыми мне довелось работать, обычно используют криптобиблиотеку Bouncy Castle . У Bouncy Castle также есть отличное введение/руководство по использованию их библиотеки. Их примеры на Java, но они довольно просты и должны быть легко перенесены на другие языки.
Существует также отличная предварительно написанная библиотека для генерации ключей JavaScript, доступная от Tom Wu по лицензии BSD.
Как обычно при шифровании по эллиптической кривой, закрытый ключ представляет собой просто случайное число. В случае secp256k1, эллиптической кривой, используемой Биткойном, это должно быть число от 1 до 115792089237316195423570985008687907852837564279074904382605163141518161494336 (или в шестнадцатеричном формате, между 0x1
и 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364140
).
Этот закрытый ключ преобразуется в открытый ключ путем умножения точек EC на базовую точку кривой. Результатом является (x,y)
пара координат, которая составляет открытый ключ.
Наконец, RIPEMD160(SHA256(pubkey))
, где pubkey — это сериализация этих координат, вычисляется и кодируется в base58 вместе с контрольной суммой. Это становится адресом.
Закрытые ключи Биткойн чаще всего отображаются в формате импорта кошелька (WIF), также известном как base58check (число, выраженное в базе 58 с контрольной суммой в конце и байтом версии в начале).
Чтобы создать закрытый ключ WIF, вам необходимо:
Вот два простых способа создания секретного показателя:
Для SECP256k1 порядок кривой следующий: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 (или 115792089237316195423570985008687907852837564279074904316L44490516314).
Это число очень близко к наибольшему 256-битному числу (0xFFF...FFF в шестнадцатеричном формате), поэтому можно ожидать, что вы никогда не превысите порядок кривой, если сгенерируете случайное 256-битное число.
Как упоминал Питер Вуилле, открытые ключи получаются путем умножения точек на базовую точку кривой и секретный показатель степени/закрытый ключ. Полученная координата (x,y) является открытым ключом.
Биткойн-адрес, как и закрытый ключ, также отображается в формате base58check. Чтобы получить адрес, делаем следующее:
Чтобы преобразовать число в формат base58check, просто выполните следующие шаги:
Вот более подробная инструкция .
Теперь, если вы не хотите беспокоиться ни о чем из этого, я бы проверил библиотеку Python Coinkit ( https://github.com/halfmoonlabs/coinkit или «pip install coinkit»).
Вы можете выполнять такие простые операции, как эти:
>>> from coinkit.keypair import BitcoinKeypair
>>> hex_private_key = '91149ee24f1ee9a6f42c3dd64c2287781c8c57a6e8e929c80976e586d5322a3d'
>>> k = BitcoinKeypair(hex_private_key)
>>> k.private_key()
'91149ee24f1ee9a6f42c3dd64c2287781c8c57a6e8e929c80976e586d5322a3d'
>>> k.public_key()
'042c6b7e6da7633c8f226891cc7fa8e5ec84f8eacc792a46786efc869a408d29539a5e6f8de3f71c0014e8ea71691c7b41f45c083a074fef7ab5c321753ba2b3fe'
>>> k.wif_pk()
'5JvBUBPzU42Y7BHD7thTnySXQXMk8XEJGGQGcyBw7CCkw8RAH7m'
>>> k.address()
'13mtgVARiB1HiRyCHnKTi6rEwyje5TYKBW'
Вы также можете создавать случайные пары ключей:
>>> k = BitcoinKeypair()
И пары ключей мозгового кошелька:
>>> passphrase = 'shepherd mais pack rate enamel horace diva filesize maximum really roar mall'
>>> k = BitcoinKeypair().from_passphrase(passphrase)
>>> k.passphrase()
'shepherd mais pack rate enamel horace diva filesize maximum really roar mall'
Раскрытие информации: я один из создателей Coinkit.
Код Javascript с http://www.bitaddress.org также может дать вам хороший пример этого.
Как они создаются, полностью задокументировано на вики : https://en.bitcoin.it/wiki/Technical_background_of_Bitcoin_addresses .
В Яве
Код:
import com.google.bitcoin.core.*;
NetworkParameters params = new MainNetParams();
String publicAddress = new DumpedPrivateKey(params,
"KzzuoFPzrPhD55icpAi7idW7z7tH8xSYo3xqTcZm3fHk3AzVxpoP").getKey()
.toAddress(params).toString();
Результат есть 17vFi4XjRibQPCktoMcGhZ3DmnG85r1VHE
.
В JavaScript
Используя javascript-библиотеку bitaddress.org :
var key = new Bitcoin.ECKey('KzzuoFPzrPhD55icpAi7idW7z7tH8xSYo3xqTcZm3fHk3AzVxpoP');
console.log(key.getBitcoinAddress());
Результат есть 17vFi4XjRibQPCktoMcGhZ3DmnG85r1VHE
.
Примечание 1: Раньше я делал bitcoin-cli getnewaddress
и bitcoin-cli dumpprivkey <pubkey>
для получения пары ключей.
Примечание 2. Чтобы упростить задачу, в своем каталоге https://github.com/pointbiz/bitaddress.org/tree/master/src просто запустите:
cat array.map.js cryptojs.js cryptojs.sha256.js cryptojs.pbkdf2.js cryptojs.hmac.js cryptojs.aes.js cryptojs.blockmodes.js cryptojs.ripemd160.js securerandom.js ellipticcurve.js secrets.js biginteger.js qrcode.js bitcoinjs-lib.js bitcoinjs-lib.base58.js bitcoinjs-lib.address.js bitcoinjs-lib.ecdsa.js bitcoinjs-lib.eckey.js bitcoinjs-lib.util.js crypto-scrypt.js > all.js
и вы получите файл размером 174 КБ, и это все, что вам нужно для запуска.
Примечание 3. Если вы хотите получить этот файл (из фиксации f6c6bbe53df28c1bf51a6216f02ad1467b36c9f7), посмотрите здесь: http://pastebin.com/raw.php?i=rH8V2j9H
Полный функциональный пример
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="http://pastebin.com/raw.php?i=rH8V2j9H"></script>
</head>
<body>
<form onsubmit="alert(new Bitcoin.ECKey(document.getElementById('pkey').value).getBitcoinAddress());">
<label>
Private key:
<input id="pkey" type="text">
</label>
</form>
</body>
</html>
производитель вещей7
Питер Уилле
Уолтер К.
Зилстра
Питер Уилле