The Spanish wiki is no longer maintained and is in read-only mode. Information contained within may be inaccurate or outdated. Please go to the English wiki for more up to date information.
Traducción automática del inglés: la wiki en español ya no se mantiene y está en modo de solo lectura. La información contenida en ella puede ser inexacta o estar desactualizada. Visite la wiki en inglés para obtener información más actualizada.
Codificación Base58Check
Las direcciones Bitcoin se codifican mediante una forma modificada de la codificación Base 58 a la que se conoce como Base58Check.
De manera general, la codificación Base58Check se utiliza para codificar secuencias de bytes utilizadas en Bitcoin convirtiéndolas en un formato de texto legible para el ser humano. Una dirección Bitcoin es simplemente una cadena de texto codificada como Base58Check que contiene unos datos útiles de 20 bytes de longitud, que consisten en el hash de la clave pública asociada con la dirección.
En el código fuente del cliente original de Bitcoin, Satoshi Nakamoto comentó la justificación del uso de Base58Check:
base58.h:
// Why base-58 instead of standard base-64 encoding? // - Don't want 0OIl characters that look the same in some fonts and // could be used to create visually identical looking account numbers. // - A string with non-alphanumeric characters is not as easily accepted as an account number. // - E-mail usually won't line-break if there's no punctuation to break at. // - Doubleclicking selects the whole number as one word if it's all alphanumeric.
Traducción: ¿Por qué codificación base-58 en lugar del estándar base-64? - No queremos los caracteres 0OIl que parecen iguales en algunas fuentes y que podrían utilizarse para crear números de cuenta visualmente idénticos. - Una cadena de texto con caracteres no alfanuméricos no tendría tan fácil aceptación como un número de cuenta. - El correo electrónico no introducirá saltos de línea si no hay signos de puntuación por los que que cortar. - El doble clic seleccionará el número completo como una sola palabra si todo es alfanumérico.
Características de Base58Check
Base58Check presenta las siguientes características:
- Datos útiles de tamaño arbitrario.
- Un conjunto de 58 símbolos alfanuméricos que incluyen letras minúsculas y mayúsculas fácilmente distinguibles (no se utilizan 0OIl).
- Un byte de información de versión/aplicación. Las direcciones Bitcoin tradicionales utilizan 0x00 para este byte. Las nuevas direcciones que permiten multifirma utilizan 0x05.
- Cuatro bytes (32 bits) de un código de comprobación de errores basado en SHA-256. Este código puede emplearse para detectar automáticamente e incluso corregir errores tipográficos.
- Un paso adicional para preservar los ceros iniciales de los datos.
Cómo crear una cadena Base58Check
Una cadena de texto Base58Check se crea a partir de un byte de versión/aplicación de la manera siguiente:
- Tomar el byte de versión/aplicación y los bytes de los datos útiles y concatenarlos (como bytes).
- Calcular SHA256(SHA256(resultado paso 1)), aplicación reiterada por dos veces del algoritmo de hash SHA-256, y quedarse con los cuatro primeros bytes.
- Concatenar los resultados del paso 1 y el paso 2 (como bytes).
- Considerar la secuencia de bytes resultado del paso 3 como un bignumber único en formato big-endian y convertirlo a base-58 utilizando transformaciones matemáticas normales(división de bignumbers) y el alfabeto de base-58 descrito más abajo. Normalizar el resultado para que no tenga ceros de base-58 (el carácter '1') iniciales.
- El carácter inicial '1', que corresponde al valor cero en base58, se reserva para representar un byte cero inicial, al principio de los datos, y no tiene valor como símbolo base-58. Puede haber uno o más caracteres '1' iniciales para representar uno o más ceros iniciales. Contar el número de bytes cero iniciales que han aparecido en el resultado del paso 3 (para las direcciones Bitcoin antiguas siempre habrá al menos uno para el byte de versión/aplicación; para las direcciones del formato multifirma más nuevo no habrá ninguno). Cada byte cero inicial estará representado por un '1' en el resultado final.
- Concatenar los caracteres '1' del paso 5 con los resultados del paso 4. Se obtiene así el resultado Base58Check.
Cómo codificar una dirección Bitcoin
Una dirección Bitcoin está basada en un par de claves criptográficas ECDSA con parámetro de curva elíptica secp256k1.
las direcciones Bitcoin son el resultado de aplicar la codificación Base58Check al valor hash del script asociado. En concreto, es Base58Check(5,RIPEMD160(SHA256(script))), con las siguientes restricciones:
- RIPEMD160 y SHA256 en este caso son siempre exactamente 20 y 32 bytes sin signo respectivamente. Están en formato big-endian (el byte más significativo en primer lugar). Han de evitarse implementaciones de valores bignumber que recortan los bytes nulos 0x00 iniciales o que agregan bytes nulos 0x00 al final para indicar el signo. El código ha de manejar bien estos casos o, de lo contrario, se generarían direcciones aparentemente válidas pero cuyos saldos nunca podrían ser gastados, con lo que se perderían sus fondos para siempre.
- El 0 se usa como byte de versión/aplicación.
Las nuevas direcciones Bitcoin multifirma que utilizan un byte de versión/aplicación 0x05 cominezan siempre con la cifra '3'.
Cómo codificar una clave privada
La codificación Base58Check se utiliza también para codificar claves privadas en el formato de importación de monedero. Este se forma exactamente igual que una dirección Bitcoin, excepto en que se utiliza 0x80 como byte de versión/aplicación y los datos útiles constan de 32 bytes en lugar de 20 (una clave privada en Bitcoin es un único entero de 32 bytes en formato big-endian). Este tipo de codificación da lugar siempre a una cadena de 51 caracteres que comienza por '5', o más concretamente '5H', '5J', o '5K'.
Tabla de símbolos Base58
La tabla de símbolos Base58 utilizada por Bitcoin es específica del proyecto Bitcoin y no tiene por qué ser igual a la de otras implementaciones de Base58 utilizadas fuera del contexto de Bitcoin.
Valor | Carácter | Valor | Carácter | Valor | Carácter | Valor | Carácter |
---|---|---|---|---|---|---|---|
0 | 1 | 1 | 2 | 2 | 3 | 3 | 4 |
4 | 5 | 5 | 6 | 6 | 7 | 7 | 8 |
8 | 9 | 9 | A | 10 | B | 11 | C |
12 | D | 13 | E | 14 | F | 15 | G |
16 | H | 17 | J | 18 | K | 19 | L |
20 | M | 21 | N | 22 | P | 23 | Q |
24 | R | 25 | S | 26 | T | 27 | U |
28 | V | 29 | W | 30 | X | 31 | Y |
32 | Z | 33 | a | 34 | b | 35 | c |
36 | d | 37 | e | 38 | f | 39 | g |
40 | h | 41 | i | 42 | j | 43 | k |
44 | m | 45 | n | 46 | o | 47 | p |
48 | q | 49 | r | 50 | s | 51 | t |
52 | u | 53 | v | 54 | w | 55 | x |
56 | y | 57 | z |
El algoritmo para codificar address_byte_string (consistente en 0x01 + hash + 4-byte_check_code) es:
code_string = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" x = convert_bytes_to_big_integer(hash_result) output_string = "" while(x > 0) { (x, remainder) = divide(x, 58) output_string.append(code_string[remainder]) } repeat(number_of_leading_zero_bytes_in_hash) { output_string.append(code_string[0]); } output_string.reverse();
Bytes de versión
En la tabla siguiente se indican algunos valores de bytes utilizados para diferenciar versiones:
Versión decimal | Símbolo inicial | Uso |
---|---|---|
0 | 1 | Hash de la clave pública Bitcoin |
5 | 3 | Hash del script Bitcoin |
21 | 4 | Clave pública (compacta) Bitcoin (propuesta) |
52 | M o N | Hash de la clave pública Namecoin |
128 | 5 | Clave privada |
111 | m o n | Hash de la clave pública Bitcoin en testnet |
196 | 2 | Hash del script Bitcoin en testnet |
En Lista de prefijos de direcciones se muestra una lista más exhaustiva.
Fuente
https://github.com/bitcoin/bitcoin/blob/master/src/base58.h
Funciones relacionadas en el código fuente
- inline string EncodeBase58Check(const vector<unsigned char>& vchIn)
- inline bool DecodeBase58Check(const char* psz, vector<unsigned char>& vchRet)
- inline bool DecodeBase58Check(const string& str, vector<unsigned char>& vchRet)