Entiendo el concepto de alto nivel. Estoy más interesado en detalles específicos. Cómo se genera una clave privada. Cómo se genera exactamente la clave pública, cómo se genera la dirección a partir de la clave pública.
Las claves públicas y privadas en una dirección de Bitcoin son un par de claves ECDSA normales. No he hurgado en esta parte particular del propio código de Bitcoin, pero los productos derivados con los que he tenido la oportunidad de trabajar normalmente usan la biblioteca criptográfica Bouncy Castle . Bouncy Castle también tiene una excelente introducción/tutorial sobre cómo usar su biblioteca. Sus ejemplos están en Java, pero es bastante simple y debería trasladarse fácilmente a otros idiomas.
También hay una excelente biblioteca escrita previamente para la generación de claves de JavaScript disponible de Tom Wu bajo la licencia BSD.
Como es normal cuando se realiza el cifrado de curva elíptica, una clave privada es simplemente un número aleatorio. En el caso de secp256k1, la curva elíptica que usa Bitcoin, tiene que ser un número entre 1 y 115792089237316195423570985008687907852837564279074904382605163141518161494336 (o en hexadecimal, entre 0x1
y 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364140
).
Esta clave privada se convierte en una clave pública realizando una multiplicación de puntos EC con el punto base de la curva. El resultado es un (x,y)
par de coordenadas, que constituye la clave pública.
Finalmente, RIPEMD160(SHA256(pubkey))
donde pubkey es una serialización de esas coordenadas, se calcula y codifica en base58, junto con una suma de verificación. Esto se convierte en la dirección.
Las claves privadas de Bitcoin se muestran más comúnmente en formato de importación de billetera (WIF), también conocido como base58check (un número expresado en base 58 con una suma de verificación al final y un byte de versión al principio).
Para crear una clave privada WIF, debe:
Aquí hay dos formas simples de generar un exponente secreto:
Para SECP256k1, el orden de la curva es 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140 (o 1157920892373161954235709850086879078528375642790749043826051631414).
Este número está muy cerca del número más grande de 256 bits (0xFFF...FFF en hexadecimal), por lo que puede esperar que nunca exceda el orden de la curva si genera un número aleatorio de 256 bits.
Como mencionó Pieter Wuille, las claves públicas se derivan realizando la multiplicación de puntos con el punto base de la curva y el exponente secreto/clave privada. La coordenada resultante (x,y) es la clave pública.
La dirección de Bitcoin, al igual que la clave privada, también se muestra en formato base58check. Para obtener la dirección, hacemos lo siguiente:
Para convertir un número al formato base58check, simplemente realice los siguientes pasos:
Aquí están las instrucciones más detalladas .
Ahora, si no quiere preocuparse por nada de esto, consultaría la biblioteca Coinkit de Python ( https://github.com/halfmoonlabs/coinkit o "pip install coinkit").
Puede realizar operaciones simples como estas:
>>> 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'
También puede crear pares de llaves aleatorios:
>>> k = BitcoinKeypair()
Y pares de llaves de billetera cerebral:
>>> 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'
Divulgación: soy uno de los creadores de Coinkit.
El código Javascript de: http://www.bitaddress.org también podría brindarle un buen ejemplo de esto.
Cómo se crean está completamente documentado en wiki : https://en.bitcoin.it/wiki/Technical_background_of_Bitcoin_addresses
en Java
El código:
import com.google.bitcoin.core.*;
NetworkParameters params = new MainNetParams();
String publicAddress = new DumpedPrivateKey(params,
"KzzuoFPzrPhD55icpAi7idW7z7tH8xSYo3xqTcZm3fHk3AzVxpoP").getKey()
.toAddress(params).toString();
El resultado 17vFi4XjRibQPCktoMcGhZ3DmnG85r1VHE
es
En JavaScript
Usando la biblioteca javascript de bitaddress.org :
var key = new Bitcoin.ECKey('KzzuoFPzrPhD55icpAi7idW7z7tH8xSYo3xqTcZm3fHk3AzVxpoP');
console.log(key.getBitcoinAddress());
El resultado 17vFi4XjRibQPCktoMcGhZ3DmnG85r1VHE
es
Nota 1: Antes, hice bitcoin-cli getnewaddress
y bitcoin-cli dumpprivkey <pubkey>
para obtener el par de claves.
Nota 2: para facilitar aún más las cosas, en su directorio https://github.com/pointbiz/bitaddress.org/tree/master/src simplemente ejecute:
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
y obtienes un archivo de 174kb que es todo lo que necesitas para ejecutar.
Nota 3: si desea obtener este archivo (del compromiso f6c6bbe53df28c1bf51a6216f02ad1467b36c9f7), busque aquí: http://pastebin.com/raw.php?i=rH8V2j9H
El ejemplo funcional completo
<!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>
fabricante de cosas7
pieter wuille
walter k
zylstra
pieter wuille