Mastering Bitcoin

Mastering Bitcoin


6. Claves, Direcciones, Carteras » Direcciones Bitcoin » Formatos de Claves

Página 29 de 98

Direcciones Bitcoin

Una dirección bitcoin es una cadena de dígitos y caracteres que puede ser compartida con cualquiera que desee enviarte dinero. Las direcciones producidas a partir de una clave pública consisten de una cadena de números y letras, comenzando por el dígito «1». Aquí hay un ejemplo de una dirección bitcoin:

1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy

La dirección bitcoin es lo que más frecuentemente aparece como el «destinatario» de los fondos. Si comparásemos una transacción bitcoin a un cheque en papel, la dirección bitcoin sería el beneficiario, es decir, lo que escribimos en la línea luego de «Páguese a la orden de». En un cheque en papel el beneficiario puede a veces ser el nombre del titular de una cuenta bancaria, pero puede incluir también corporaciones, instituciones, o incluso efectivo. El hecho de que los cheques en papel no requieran de especificar una cuenta, sino que en cambio usan un nombre abstracto como destinatario de los fondos, los convierte en instrumentos de pago muy flexibles. Las transacciones bitcoin usan una abstracción similar para ser muy flexibles: la dirección bitcoin. Una dirección bitcoin puede representar al propietario del par de clave privada y pública, o puede representar otra cosa, como un script de pago, como veremos en el apartado sobre el pago con script hash (P2SH). Por ahora examinemos el caso simple: una dirección bitcoin que representa y es derivada de una clave pública.

La dirección bitcoin se obtiene de la clave pública a través del uso de hashing criptográfico de sentido único. Un «algoritmo de hashing», o simplemente un «algoritmo de hash» es una función de sentido único que produce una huella o «hash» a partir de una entrada de tamaño arbitrario. Las funciones de hash criptográfico se usan extensivamente en bitcoin: en las direcciones bitcoin, en las direcciones de script, y en algoritmo de prueba de trabajo de minado. Los algoritmos usados para crear direcciones bitcoin a partir de claves públicas son el Secure Hash Algorithm (SHA) y el RACE Integrity Primitives Evaluation Message Digest (RIPEMD), específicamente SHA256 y RIPEMD160.

A partir de la clave pública K computamos el hash SHA256 y luego computamos el hash RIPEMD160 del resultado, produciendo un número de 160 bits (20 bytes):

Donde K es la clave pública y A es la dirección bitcoin resultante.

Una dirección bitcoin no es lo mismo que una clave pública. Las direcciones bitcoin se obtienen de una clave pública a través de una función de sentido único.

Las direcciones bitcoin son casi siempre presentadas a los usuarios en una codificación llamada «Base58Check» (ver Codificación Base58 y Base58Check), la cual usa 58 caracteres (un sistema numérico de base 58) y un checksum para ayudar a la legibilidad humana, evitar ambigüedad y proteger de errores en la transcripción y entrada de direcciones. Base58Check también se usa en muchas otras formas en bitcoin, siempre que haya una necesidad de que un usuario lea y transcriba un número correctamente, tal como una dirección bitcoin, una clave privada, una clave encriptada, o un hash de script. En la siguiente sección examinaremos las mecánicas de la codificación y decodificación de Base58Check y las representaciones resultantes. Clave pública a dirección bitcoin: conversión de una clave pública en una dirección bitcoin ilustra la conversión de una clave pública a una dirección bitcoin.

Figura 5. Clave pública a dirección bitcoin: conversión de una clave pública en una dirección bitcoin

Codificación Base58 y Base58Check

Para representar números largos en forma compacta, usando menos símbolos, muchos sistemas informáticos utilizan representaciones alfanuméricas mezcladas con una base mayor a 10. Por ejemplo, mientras el sistema decimal tradicional utiliza 10 numerales, de 0 a 9, el sistema hexadecimal usa 16, con letras de la A a la F como los seis símbolos adicionales. Un número representado en formato hexadecimal es más breve que su equivalente representación decimal. Aun más compacta, la representación Base-64 usa 26 letras minúsculas, 26 letras mayúsculas, 10 numerales y dos carácteres más como «+» y «/» para transmitir datos binarios sobre medios de texto plano, tal como email. Base-64 es más comúnmente usado para añadir adjuntos binarios en emails. Base58 es un formato de codificación binaria basada en texto desarrollada para su uso en bitcoin y utilizada en muchas otras criptomonedas. Ofrece un balance entre representación compacta, legibilidad y detección y prevención de errores. Base58 es un subconjunto de Base64, usando las letras mayúsculas y minúsculas y números, pero omitiendo algunos carácteres que a menudo son confundidos por otros y pueden verse idénticos cuando se representan con ciertas fuentes. Específicamente, Base58 es Base64 sin el 0 (número cero), O (letra o mayúscula), l (letra L minúscula), I (letra i mayúscula) y los símbolos «\+» y «/». O, puesto de forma más sencilla, es el conjunto de letras mayúsculas y minúsculas y números sin los cuatro (0, O, l, I) que acabamos de mencionar.

Ejemplo 1. Alfabeto Base58 de bitcoin

123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

Para añadir seguridad extra contra errores tipográficos o de transcripción, Base58Check es un formato de codificación de Base58, usado frecuentemente en bitcoin, el cual posee un código de chequeo de errores. El checksum consiste de cuatro bytes adicionales añadidos al final de los datos siendo codificados. El checksum es derivado del hash de los datos codificados y puede por ende ser usado para detectar y prevenir errores de transcripción o tipeo. Cuando el código de decodificación es presentado con un código Base58Check calculará el checksum de los datos y lo comparará con el checksum incluido en el código. Si no son idénticos significa que ha habido un error y el código Base58Check es inválido. Por ejemplo, esto previene que una dirección bitcoin tipeada erróneamente sea aceptada por el software de cartera como un destinatario válido, un error que de lo contrario resultaría en la pérdida de fondos.

Para convertir datos (un número) al formato Base58Check primero agregamos un prefijo a los datos, llamado el «byte de versión», el cual sirve para identificar fácilmente el tipo de datos siendo codificados. Por ejemplo, en el caso de una dirección bitcoin el prefijo es cero (0x00 en hexadecimal), mientras que el prefijo usado cuando se codifica una clave privada es 128 (0x80 en hexadecimal). Una lista de prefijos de versión comunes puede verse en Prefijos de versión Base58Check y ejemplos de resultados codificados.

A continuación computamos el checksum «doble SHA», lo que significa que aplicamos el algoritmo de hash SHA256 dos veces sobre resultado previo (prefijo y datos):

checksum = SHA256(SHA256(prefijo+datos))

Figura 6. Codificación Base58Check: un formato Base58, con versión y checksum para codificar datos bitcoin sin ambigüedades

Del hash de 32 bytes resultante (hash de un hash) tomamos solo los primeros cuatro bytes. Estos cuatro bytes sirven como el código de chequeo de error, o checksum. El checksum es concatenado (o anexado) al final.

El resultado está compuesto de tres elementos: un prefijo, los datos y un checksum. Este resultado es codificado usando el alfabeto Base58 descrito anteriormente. Codificación Base58Check: un formato Base58, con versión y checksum para codificar datos bitcoin sin ambigüedades ilustra el proceso de codificación Base58Check.

En bitcoin la mayoría de los datos presentados al usuario son codificados usando Base58Check para hacerlos compactos, fáciles de leer, y facilitar la detección de errores. El prefijo de versión en la codificación Base58Check se usa para crear formatos distinguibles fácilmente, los cuales al ser codificados en Base58 contienen caracteres específicos al principio de la carga codificada en Base58Check. Estos caracteres facilitan a humanos la identificación del tipo de los datos codificados y cómo usarlos. Esto es lo que diferencia, por ejemplo, a las direcciones bitcoin codificadas en Base58Check comenzadas en 1 del formato WIF de claves privada codifacada en Base58Check comenzadas en 5. Algunos ejemplos de prefijos de versión y sus caracteres Base58 resultantes se muestran en Prefijos de versión Base58Check y ejemplos de resultados codificados.

Tabla 1. Prefijos de versión Base58Check y ejemplos de resultados codificados

Veamos el proceso completo de creación de una dirección bitcoin, partiendo de una clave privada, a una clave pública (un punto en la clave elíptica) a una dirección doblemente hasheada y finalmente la codificación Base58Check. El código C++ Creando una dirección bitcoin codificada en Base58Check a partir de una clave privada muestra el proceso completo paso a paso, desde clave privada hasta dirección bitcoin codificada en Base58Check. El código de ejemplo usa la biblioteca libbitcoin presentada en el apartado referido a clientes alternativos, librerías y herramientas para algunas funciones útiles.

Ejemplo 2. Creando una dirección bitcoin codificada en Base58Check a partir de una clave privada

#include <bitcoin/bitcoin.hpp>

int main()

{

// Private secret key.

bc::ec_secret secret;

bool success = bc::decode_base16(secret,

"038109007313a5807b2eccc082c8c3fbb988a973cacf1a7df9ce725c31b14776"); assert(success);

// Get public key.

bc::ec_point public_key = bc::secret_to_public_key(secret);

std::cout << "Public key: " << bc::encode_hex(public_key) << std::endl;

// Create Bitcoin address.

// Normally you can use:

// bc::payment_address payaddr;

// bc::set_public_key(payaddr, public_key);

// const std::string address = payaddr.encoded();

// Compute hash of public key for P2PKH address.

const bc::short_hash hash = bc::bitcoin_short_hash(public_key);

bc::data_chunk unencoded_address;

// Reserve 25 bytes

// [ version:1 ]

// [ hash:20 ]

// [ checksum:4 ]

unencoded_address.reserve(25);

// Version byte, 0 is normal BTC address (P2PKH).

unencoded_address.push_back(0);

// Hash data

bc::extend_data(unencoded_address, hash);

// Checksum is computed by hashing data, and adding 4 bytes from hash.

bc::append_checksum(unencoded_address);

// Finally we must encode the result in Bitcoin's base58 encoding

assert(unencoded_address.size() == 25);

const std::string address = bc::encode_base58(unencoded_address);

std::cout << "Address: " << address << std::endl; return 0;

}

El código usa una clave privada predefinida de forma que produzca la misma dirección bitcoin cada vez que es ejecutado, como se muestra en Compilando y ejecutando el código addr.

Ejemplo 3. Compilando y ejecutando el código addr

# Compilando el código addr.cpp

$ g++ -o addr addr.cpp $(pkg-config --cflags --libs libbitcoin)

# Correr el ejecutable addr

$ ./addr

Public key: 0202a406624211f2abbdc68da3df929f938c3399dd79fac1b51b0e4ad1d26a47aa Address: 1PRTTaJesdNovgne6Ehcdu1fpEdX7913CK

Formatos de Claves

Tanto las claves privadas como públicas pueden ser representadas en un número de formatos distintos. Todas estas representaciones codifican el mismo número a pesar de verse diferentes. Estos formatos se usan principalmente para facilitar el trabajo a las personas al leer y transcribir claves sin introducir errores.

Ir a la siguiente página

Report Page