Criptografía aplicada: Cálculo del hash SHA-256 de un bloque Bitcoin

2
10,411
Novatica Blockchain 241

Resumen

Este documento presenta en detalle un análisis criptográfico sobre cada una de las partes de las que se compone un bloque de datos en el criptosistema definido por el protocolo Bitcoin1. Se tratarán algunos aspectos importantes como los  diferentes  datos,  tipos,  formatos  y  la  distribución  de  los  mismos  en  la  estructura del bloque, así como las operaciones lógico matemáticas de la función criptográfica SHA-2562 que se emplean con el fin de generar un hash  resultante adecuado, es decir, un resultado que cumpla las características definidas en el protocolo Bitcoin. Finalmente este hash  representará dicho bloque en lo que se conoce como la cadena de bloques, o como el propio creador Satoshi Nakamoto lo llamaba originalmente, timechain3. Todos los datos utilizados en los ejemplos, así como en los cálculos, son datos reales pertenecientes al bloque número #286819 de la cadena de bloques de Bitcoin en la red principal mainnet. No existe  ninguna  razón  especial  en  la  elección  de  este  bloque,  es  uno  al  azar.  El lector puede consultar los datos de este o cualquier otro bloque, bien en la cadena de bloques descargada en su computadora local o bien en un explorador de bloques online4, y realizar los mismos cálculos en todos los casos, obviamente obteniendo resultados diferentes.

Javier Domínguez Gómez

Cryptographer & Software Engineer

Javier Dominguez Gomez

Miembro y hacktivista de la Free Software Foundation y la Electronic Frontier Foundation, desde donde se promueve la privacidad y se lucha por los derechos de los usuarios de plataformas digitales. Ingeniería de software y programador de bajo y medio nivel en Assembly, C y C++, con predilección por los sistemas GNU y Unix, los sistemas digitales, la criptografía y steganografía. Colabora como profesor (teaching fellow) del master en Big Data de la universidad Complutense de Madrid. Radioaficionado, apasionado de las comunicaciones y la Seguridad Operacional (OPSEC).

1. Introducción

1.1. Formatos en el texto

A lo largo de este documento el lector encontrará algunas palabras o bloques de texto con diferentes formatos o tipografía. Se mostrarán en letra cursiva  las palabras  en  inglés  o  que  hagan  referencia  a  algún  término  técnico.  Resaltadas o en negrita aquellas palabras que describen una propiedad, una variable o un nombre de fichero, y finalmente con tipografía courier aquellos datos que representen un valor hexadecimal o base 16, o fragmentos de código fuente en diferentes lenguajes de programación.

1.2. Objetivo

Este documento presenta en detalle un análisis criptográfico sobre cada una de las partes de las que se compone un bloque de datos en el criptosistema definido por el protocolo Bitcoin[1]. Se tratarán algunos aspectos importantes como los  diferentes  datos,  tipos,  formatos  y  la  distribución  de  los  mismos  en  la  estructura del bloque, así como las operaciones lógico matemáticas de la función criptográfica SHA-256 que se emplean con el fin de generar un hash  resultante adecuado, es decir, un resultado que cumpla las características definidas en el protocolo Bitcoin. Finalmente este hash  representará dicho bloque en lo que se conoce como la cadena de bloques, o como el propio creador Satoshi Nakamoto lo llamaba originalmente, timechain[2]. Todos los datos utilizados en los ejemplos, así como en los cálculos, son datos reales pertenecientes al bloque número #286819 de la cadena de bloques de Bitcoin en la red principal mainnet. No existe  ninguna  razón  especial  en  la  elección  de  este  bloque,  es  uno  al  azar.  El lector puede consultar los datos de este o cualquier otro bloque, bien en la cadena de bloques descargada en su computadora local o bien en un explorador de bloques online, y realizar los mismos cálculos en todos los casos, obviamente obteniendo resultados diferentes.

1.3. A quién va dirigido

El documento va dirigido a principalmente a lectores familiarizados con la criptología  en  cualquiera  de  sus  dos  ramas:  la  criptografía  y  el  criptoanálisis. También va dirigido a estudiantes de ciencias de la computación o matemáticas, en general a lectores que todavía no se han adentrado en el campo de del análisis forense criptográfico sobre la información que contiene un bloque de la cadena de bloques de Bitcoin, pero que quieren comprender su funcionamiento al más bajo nivel, a nivel de bits. El texto trata de facilitar al lector la información sobre los métodos empleados para obtener un hash que cumpla una serie de requisitos según el criptosistema planteado por el protocolo Bitcoin. Para ello será necesario tener de antemano unos conocimientos mínimos sobre matemática discreta, álgebra  de  Boole[3],  conversión  de  datos  en  diferentes  bases  como  binario,  decimal y hexadecimal, y comprender cómo funcionan algunas operaciones lógicas, módulo, rotativas y de desplazamiento de bits.

2. Estructura de datos de un bloque

Cuando se hace referencia a un bloque en realidad se está haciendo referencia a un conjunto de datos ordenados en base a unas normas, que en el caso que nos atañe se definen cuando se desarrolla el protocolo Bitcoin, creando así una estructura de datos ordenada y segmentada de forma que sea sencillo identificar cada una de las partes. Los datos se ordenan en 5 secciones principales. La primera sección se reserva para un dato denominado magicId, un dato numérico de  4  bytes  y  la  segunda  sección  para  almacenar  el  dato  size,  al  igual  que  el anterior  también  es  un  dato  numérico  de  4  bytes,  este  representará  el  tamaño final  del  bloque.  En  los  siguientes  puntos  se  explicará  en  detalle  cada  uno de los datos. Estos dos segmentos juntos se pueden usar como el delimitador   que separa un bloque de otro en la cadena, pues los bytes que conforman los datos  de  los  bloques  se  representan  concatenados  uno  a  continuación  de  otro. La siguiente imagen representa la estructura de un bloque en el que se muestra resaltado en color verde el segmento que alberga el dato magicId y en amarillo el segmento que alberga el dato size, ambos seguidos por el resto de datos del bloque, la zona de color gris punteada.

Novatica Blockchain 241
Figura 1: Los dos primeros segmentos de datos concatenados de cada bloque.

El tercer segmento tiene un espacio de memoria reservado de 80 bytes para almacenar los datos de la cabecera o header. El cuarto segmento almacenará un dato denominado transactionCount que representa el número de transacciones que contiene el bloque, será un número de tipo entero sin signo y el tamaño puede variar dependiendo del número de transacciones en cada bloque. Por último, el quinto segmento se reserva para almacenar todos los datos de los que se componen cada una de las transacciones, esta sección llamada transaction data  tendrá  un  tamaño  variable  que  se  corresponde  con  el  tamaño  disponible  o restante  hasta  completar  el  bloque.  A  continuación  una  representación  gráfica de los 5 segmentos de datos de los que se compone cada bloque.

Novatica Blockchain 241
Figura 2: Los 5 bloques de datos principales en cada bloque de la cadena.

El segmento header a su vez se compone de 6 datos que son versionNumber, previousBlockHash, merkleRoot, timeStamp targetDifficulty o nonce. Todos los datos del bloque tienen sus propios atributos, como puede ser el tipo de dato o tipo primitivo, un nombre, el tamaño que ocupa en memoria y el  formato  en  el  que  este  se  representará  finalmente.  En  la  siguiente  tabla  se categorizan los datos más significativos y a continuación se explican en detalle.

Novatica Blockchain 241
Cuadro 1: Principales datos de un bloque en la cadena de bloques de Bitcoin.

1. magicID: En la red de Bitcoin se establecen conexiones entre los nodos con la finalidad de establecer una comunicación para el envío y recepción de datos o mensajes. Los mensajes se envían mediante un canal en el que según  van  llegando  se  van  concatenando  uno  detrás  de  otro.  Así  pues, cuando  se  desarrolló  el  protocolo  Bitcoin  se  vio  conveniente  añadir  un prefijo en cada mensaje anteponiendo este dato de 4 bytes y así poder identificar  fácilmente  no  solo  la  red  de  Bitcoin  en  la  que  se  generan,  si no también dónde empieza y termina cada mensaje que circula entre los diferentes nodos de la red. La siguiente tabla muestra los diferentes valores que puede tener la variable magicID dependiendo de la red.

Red magicID
Mainnet 0xf9beb4d9
Testnet  0xfabfb5da
Testnet3 0x0b110907
Namecoin 0xf9beb4fe
Regtest 0xfabfb5da

Se decidió establecer estos valores tan específicos dada la improbabilidad de que los caracteres ASCII que representan se encuentren en un mensa- je  estándar,  tal  y  como  se  indica  en  el  archivo  chainparams.cpp[4]  que  lo implementa en el código de Bitcoin.

2. size: En un dato numérico hexadecimal de 4 bytes de valor variable que representa la longitud en bytes del bloque actual. Está codificado en formato Little-endian.  Por  ejemplo,  un  bloque  con  tamaño  152.509  KB  tendrá  el siguiente valor:

15250910 = 0x000253BD ⇒ 0xBD530200

3. versionNumber: Este dato hexadecimal puede cambiar de valor cuando se  actualiza  el  software  y  cambia  el  número  de  la  versión  del  protocolo. Tiene  un  tamaño  de  4  bytes  y  se  codifica  en  formato  Little-endian,  por ejemplo:

210 = 0x00000002 ⇒ 0x02000000

4. previousBlockHash: Se trata del hash o digest resultante del bloque anterior  tras  aplicar  las  funciones  criptográficas  utilizando  los  datos  de la cabecera de dicho bloque. Tiene una longitud de 256 bits o 32 bytes codificado en formato Big-endian. Tal y como se explica al inicio del este documento el ejemplo en todo caso toma los datos correspondientes al bloque #286819, así pues, el valor de este dato ha de ser el hash resultante del bloque anterior, que en este caso es el bloque #286818[5].

000000000000000117c80378b8da0e33559b5997f2ad55e2f7d18ec1975b9717

5. merkleRoot:  Cada  vez  que  una  nueva  transacción  es  aceptada  el  valor de esta variable se modifica. Se trata de un hash hexadecimal de 32 bytes codificado  en  formato  Big-endian.  Para  obtener  el  hash  final,  también llamado hash root se han de concatenar los datos de las transacciones ubicados en los nodos hoja del árbol, en grupos de dos. De ese modo, por cada dos transacciones se obtiene un hash  nuevo que será incluido en un nuevo vector que repetirá la acción hasta llegar al hash root.

Novatica Blockchain 241
Figura 3: Ejemplo de árbol de Merkle con 5 nodos hoja.

Cada  uno  de  los  vectores  v    =  ( v1, v2, . . . , vn−1, vn) irá  reduciendo  el número de nodos o elementos mediante la siguiente función recursiva por intervalos o algoritmo de complejidad O(n).

Novatica Blockchain 241

A continuación un ejemplo escrito en lenguaje C++ que implementa dicho algoritmo[8]:

Novatica Blockchain 241

6. timeStamp: Se trata de un número entero sin signo de 4 bytes  también llamado Epoch  o  Tiempo Unix.  Representa  el  número  de  segundos  que han transcurrido desde el 1 de enero de 1970 a las 00:00:00. Se codifica en formato Little-endian.

Un ejemplo de cómo se puede calcular este dato es mediante el siguiente código  escrito  en  lenguaje  C.  Nótese  que  las  horas  se  procesan  como GMT+1.

 

Novatica Blockchain 2417. targetDifficulty: A este dato también se le llama simplemente target  o “Bits” si se hace referencia al empaquetado de datos en el bloque. Se trata de  un  número  entero  de  256  bits  representado  como  un  número  decimal muy  grande,  tanto  que  abarcaría  el  rango  de  números  existentes  entre  0 y  2256  —  1.  El  siguiente  número  sería  el  valor  hexadecimal  máximo  que podría tomar la variable targetDifficulty.

Novatica Blockchain 241
En el bloque se almacena como un número decimal de coma flotante truncando, por ejemplo, el valor hexadecimal anterior quedaría representado de la siguiente forma.

Novatica Blockchain 241
La  dificultad  es  el  resultado  de  dividir  el  valor  máximo  entre  el  valor actual de la variable targetDifficulty, tal y como se muestra en la siguiente fórmula.

Novatica Blockchain 241A continuación un fragmento de código escrito en lenguaje C++ que realiza el cálculo y que se puede emplear para hallar la dificultad de minado.

Novatica Blockchain 241

Hay que tener en cuenta el valor de la variable targetDifficulty en cada caso, por ejemplo en el bloque #286819 dicho valor es 0x19015f53. Es una de las variables más importantes a tener en cuenta a la hora de obtener el hash adecuado del bloque antes de incorporarlo a la cadena como un bloque válido. Así pues la prueba de trabajo o Proof  of  Work  tendrá mayor o menor dificultad. En el protocolo de Bitcoin se define una regla que dice que el hash del bloque ha de ser un número menor o igual al valor de esta variable targetDifficulty en ese momento. De modo que si el hash obtenido  como  candidato  a  generar  un  bloque  fuese  un  número  menor  o igual al de targetDifficulty habría posibilidades para que el hash candidato sea válido para generar un nuevo bloque, aunque de forma adicional se han de cumplir otras condiciones. Por el contrario, si el hash obtenido como candidato fuera un número mayor que el valor de esta variable targetDifficulty, este quedaría desestimado, entonces habría que incrementar el valor de la variable nonce y repetir todo el proceso para generar un hash nuevo. El  siguiente  gráfico muestra  la  variación  de  la  dificultad  a  lo  largo  del tiempo.

Novatica Blockchain 241
Figura 4: Dificultad de minado desde enero de 2009 hasta hoy.

El  valor  de  la  variable  targetDifficulty  se  modifica  automáticamente una vez se han generado 2016 bloques, esto sucede aproximadamente cada dos semanas. El nuevo valor se obtiene mediante un cálculo que realizan todos los clientes Bitcoin de la red en el que toman el tiempo real que ha llevado generar los 2016 bloques y se obtiene la diferencia porcentual respecto al número de bloques que se esperaba haber calculado en el periodo de dos semanas.  Cuanto  menor  sea  el  valor  de  la  variable  targetDifficulty  más aumentará la dificultad para hallar un hash  válido para el bloque.

8. nonce: Se trata de un número entero sin signo aleatorio con una longitud de 32 bits o 4 bytes codificado en formato Little-endian. Es el dato que ha de cambiarse tras un intento fallido por encontrar el hash del bloque adecuado, de modo que al incrementarlo se han de realizar de nuevo todos los cálculos de la función SHA-256 teniendo en cuenta el nuevo valor de esta variable. Siguiendo con el ejemplo del bloque #286819, este se incorporó a la cadena de bloques con un valor decimal o base 10 para la variable nonce de 856192328, lo que indica casi con total seguridad que se tuvieron que realizar bastantes intentos.

9. transactionCount: En el caso de transactionCount el tipo de dato es un entero sin signo de longitud variable. Como el propio nombre indica, dependiendo del número de transacciones que han sido procesadas tendrá un valor numérico u otro.

*Cuando se le asigna por valor un entero muy grande se codifica en formatoLittle-endian.

2.1. Datos de la cabecera o header

La siguiente imagen es una captura de pantalla de los datos del bloque #286819 visualizados en un explorador de bloques. Se han resaltado los datos que forman parte de la cabecera o header del bloque.

Novatica Blockchain 241
Figura 5: Datos empleados para la obtención del hash  del bloque #286819.

3. Construcción  de  la  cadena  de  entrada  M

Siguiendo con el ejemplo del bloque #286819 de la cadena de bloques de Bitcoin, dicho bloque está representado mediante el siguiente hash.

0000000000000000e067a478024addfecdc93628978aa52d91fabd4292982a50

A continuación los datos correspondientes a la cabecera o header  del bloque:

Version: 2
Prev. Block: 000000000000000117c80378b8da0e33559b5997f2ad55e2f7d18ec1975b9717
Merkle root: 871714dcbae6c8193a2bb9b2a69fe1c0440399f38d94b3a0f1b447275a29978a
Timestamp: 2014-02-20 04:57:25 (Epoch timestamp: 1392872245)
Bits: 419520339
Nonce: 856192328

En este punto hay que pasar los datos en formato decimal a formato hexadecimal, de modo que quedarían de la siguiente manera:

Version: 00000002
Prev. Block: 000000000000000117c80378b8da0e33559b5997f2ad55e2f7d18ec1975b9717
Merkle root: 871714dcbae6c8193a2bb9b2a69fe1c0440399f38d94b3a0f1b447275a29978a
Timestamp: 53058B35
Bits: 19015F53
Nonce: 33087548

Ahora hay que reorganizar los datos en formato Little-Endian:

Finalmente se concatenan uno a continuación de otro, empezando por version, seguido del hash del bloque anterior, merkle root, timestamp, bits y nonce, formando  una  cadena  de  entrada  de  160  carácteres  hexadecimales  con un tamaño total de 640 bits.

Novatica Blockchain 241

Se segmenta la cadena de entrada M en bloques de 32 bits:

Novatica Blockchain 241De este modo se obtiene el mensaje de entrada M. Se ha de reservar este dato para  utilizarlo  más  adelante  en  la  función  SHA-256  como  input  en  la  primera ronda.

3.1. Longitud de la cadena de entrada M

Una vez que se ha obtenido la cadena de entrada M en el punto anterior es necesario calcular la longitud de la misma en formato hexadecimal o base 16, es decir, 640 bits que se representan con el valor 280 en hexadecimal.

|M | = 280 (640 bits del mensaje original en hexadecimal)

Este  dato  se  ha  de  reservar  para  el  siguiente  punto,  ya  que  será  necesario para completar los registros W14 y W15 de la variable Wt solo en la segunda y tercera ejecución de la función SHA-256.

3.2. La variable Wt

Tal y como se describe en el punto 3 del documento “Criptografía aplicada: Función SHA-25612, la variable Wt es un vector de 64 elementos que contiene palabras  hexadecimales  de  32  bits. Tiene  un  tamaño  o  longitud  de  2048  bits (256  bytes)  y  se  obtiene  mediante  la  siguiente  función  recursiva  definida  por intervalos.

Novatica Blockchain 241

En la anterior función recursiva definida por intervalos, el primer intervalo es el que abarca los 16 primeros registros, o sea desde W0 hasta W15. El segundo intervalo es el esquema de los 48 registros restantes, es decir, desde W16 hasta W63.

Novatica Blockchain 241
Figura 6: Representación gráfica de Wt.

Las funciones σ0  y σ1  realizan las siguientes operaciones lógicas de compresión  con  cada  uno  de  los  bits  de  la  palabra  almacenada  en  el  segmento  de  Wt que procesan.

σ0(x) = ROT R7(x) ⊕ ROT R18(x) ⊕ SHR3(x)

σ1(x) = ROT R17(x) ⊕ ROT R19(x) ⊕ SHR10(x)

Para hallar el valor de cualquiera de los segmentos que van desde W16 hasta W63 se han de realizar las siguientes operaciones, donde i tiene por valor el valor de t en el segmento que se quiere calcular de Wt. Por ejemplo, para W16:

σ1(Wi−2) + Wi−7 + σ0(Wi−15) + Wi−16

σ1(W16−2) + W16−7 + σ0(W16−15) + W16−16

σ1(W14) + W9 + σ0(W1) + W0

En este ejemplo los segmentos W14, W9, W1 y W0 de la primera ronda (Ronda#0 ) tienen asignados los siguientes valores:

W14 = 0xb2b92b3a          W9 = 0x8a97295a

W1 = 0x17975b97                W0 = 0x02000000

A continuación se muestra una representación gráfica la operación lógica de compresión σ1, que aplica sobre el valor del segmento W14.

Novatica Blockchain 241
Figura 7: Operación ROT  R17(x) ⊕ ROT  R19(x) ⊕ SHR10(x) con cada bit.

Tras  el  cálculo  de  σ1(W14)  se  obtiene  la  palabra  hexadecimal  de  32  bits 0xb0d6a141. Se ha de reservar este valor para calcular el resultado final. También  se  muestra  la representación  gráfica  la  operación  lógica  de  compresión σ0, que aplica sobre el valor del segmento W1.

Novatica Blockchain 241
Figura 8: Operación ROT  R7(x) ⊕ ROT  R18(x) ⊕ SHR3(x) con cada bit.

Tras  el  cálculo  de  σ0(W1)  se  obtiene  la  palabra  hexadecimal  de  32  bits fa380020.  Una  vez  realizados  los  cálculos  necesarios  para  obtener  el  valor de σ1(W14) y σ0(W1) finalmente se ha de realizar la siguiente operación final.

Novatica Blockchain 241
Figura 9: Operación final mod 232(σ1(W14), W9, σ0(W1), W0).

De  este  modo  se  obtiene  el  valor  que  se  almacenará  en  el  segmento  W16 del  vector  Wt.  Será  necesario  repetir  el  mismo  proceso  por  cada  uno  de  los segmentos hasta llegar a W63.

Todos  los  cálculos  anteriores  también  aplican  a  las  reglas  criptográficas  de los bloques en el protocolo Bitcoin, solo que hay que tener en cuenta que la cadena de entrada M en cada bloque tiene una longitud superior a 512 bits, lo que implica utilizar la función hash SHA-256 tres veces, una por cada ronda, y el valor de la longitud de M solo se aplicará en el esquema de relleno de la segunda y tercera ronda. En la primera ronda (Ronda #0 ) se rellenan los primeros 16 segmentos de la variable Wt con todos los bytes en hexadecimal que quepan, es decir, los primeros 512 bits  de M , rellenando también los segmentos W14 y W15.

Los 128 bits restantes de la cadena de entrada M que no caben en esta primera ronda se reservan para los primeros 4 registros de Wt de la segunda ronda. Tras  la segunda ronda (Ronda #1 ) se obtiene un digest de 256 bits que se utiliza para rellenar  los  primeros  8  segmentos  de  Wt  en  la  tercera  y  última  ronda  (Ronda #2 ). La siguiente figura se detalla el contenido de los primeros 16 registros de   la variable Wt en cada una de las tres veces que se ejecutan las 64 iteraciones de la función SHA-256 para obtener el digest en cada caso.

Novatica Blockchain 241
Figura 10: Los primeros 16 registros de la variable Wt en los tres casos en los que se ha de ejecutar la función SHA-256.

En los siguientes puntos se detalla el esquema de relleno al completo en cada una de las rondas.

3.3. Primera ronda SHA-256: Ronda 0

Novatica Blockchain 241La función hash SHA-256 realiza 64 ciclos criptográficos en los que procesará una  serie  de  cálculos  en  los  que  tiene  en  cuenta  por  un  lado  las  8  palabras hexadecimales de 32 bits asignadas como valor a las variables A, B, C, D, E, F , G y H, y por otro lado la variable Wt, que es un vector de 64 elementos ordenados por intervalos. En la primera ronda criptográfica se han iniciar los valores de las variables A0, B0, C0, D0, E0, F0, G0 y H0 con los valores estándar de la función hash  SHA- 256 en su primera iteración, es decir, los 32 primeros bits en hexadecimal o base 16 de la parte fraccionaria de  las  raíces  cuadradas  de  los  primeros  8  números primos.

Novatica Blockchain 241

En una función SHA-256, cuando el tamaño de la cadena de entrada M es igual o mayor que 512 bits se han de rellenar los primeros 16 elementos del vector Wt con los primeros 512 bits de la cadena principal de entrada M , incluidos los elementos W14 y W15, tal y como se muestra en la imagen. El resto de la cadena M  se ha de reservar para la segunda ejecución de la función SHA-256 que se explicará en el siguiente punto. Teniendo la cadena M de entrada, las 8 palabrasiniciales, que irán cambiando en cada una de las 64 iteraciones, y los 64 elementos del vector Wt se puede comenzar a realizar las operaciones de la función SHA-256. El objetivo en esta primera ronda es obtener el primer hash, necesario en la segunda ronda.

Cuando se hayan realizado las 64 iteraciones SHA-256 con los datos anteriores  se  ha  de  realizar  una  última  operación  en  la  que  se  ha  de  tomar  cada palabra A, B, C, D, E, F , G y H de la primera iteración y realizar una operación mod 232  con su homóloga de la última iteración, véase el ejemplo.

Novatica Blockchain 241
Finalmente se concatenan los valores de los 8 resultados en esta ronda 0 obteniendo el siguiente digest resultante:

dc6a3b8d0c69421acb1a5434e536f7d5c3c1b9e44cbb9b8f95f0172efc48d2df

Se reserva este dato para realizar la segunda ronda SHA-256 en el siguiente punto.

3.4. Segunda ronda SHA-256: Ronda 1

En la segunda ronda se han volver a realizar los 64 ciclos criptográficos que realiza SHA-256 teniendo en cuenta que el valor de las 8 palabras iniciales A, B, C, D, E, F , G y H en la primera iteración tendrán por valor inicial cada uno de los segmentos de 32 bits correspondientes al hash resultante de la primera ronda.

Novatica Blockchain 241

Novatica Blockchain 241En cuanto a los primeros 16 registros de la variable Wt en esta segunda ronda se utilizarán primero los bits  del mensaje M original de 640 bits que no cabían en la ronda anterior.

dc141787 + 358b0553 + 535f0119 + 48750833

A continuación hay que tomar un bit  que represente el  número  1  decimal  o  base  10,  es  decir  00000001, este  se  desplaza  al  bit  más  alto  del  byte,  con  lo  que se obtiene 10000000 y finalmente se calcula el valor hexadecimal, que es 80.

100000002 = 8016

Independientemente de la longitud de cadena hexadecimal de la palabra de entrada, se añade 80 por la derecha.

486f6c61 + 206d756e + 646f + 80

Ahora  hay  que  añadir  a  la  cadena  una  cantidad  de bits con valor 0 hasta llegar a 448 bits  en total, que  es la longitud que abarca todos los intervalos que van desde W0 hasta W13. Para terminar de completar los primeros 16 segmentos de Wt solo queda rellenar los últimos dos bloques de 32 bits W14 y W15 con la longitud del mensaje de entrada |M| en hexadecimal, con tantos ceros por la izquierda como sean necesario para alcanzar 64 bits de longitud, en este caso es 280. Los valores que irán en los segmentos desde W16 hasta W63 se obtienen siguiendo las pautas explicadas en el punto 6 de este documento. Al igual que en la primera ronda, cuando se hayan realizado las 64  iteraciones  SHA-256  con  los  datos  anteriores  se  ha  de  realizar  una  última operación en la que se ha de tomar cada palabra A, B, C, D, E, F , G y H de la  primera  iteración  y  realizar  una  operación  mod 232 con su homóloga de  la última iteración, véase el ejemplo.

Novatica Blockchain 241

Finalmente se concatenan los valores de los 8 resultados en esta ronda 1 obteniendo el siguiente digest resultante:

7c122b86287a3ef7eac247e0ad637091ccfecbf85f6213030d9c1f895515d9e6

Se reserva este dato para realizar la tercera ronda SHA-256 en el siguiente punto.

3.5. Tercera ronda SHA-256: Ronda 2

Novatica Blockchain 241En esta tercera ronda criptográfica (Ronda #2 ) se ha de utilizar como mensaje de entrada M el hash obtenido en la ronda anterior (Ronda #1 ). Al igual que en la ronda anterior hay que tomar un bit que represente el número 1 decimal o base 10, es decir 00000001, este  se  desplaza  al  bit  más  alto  del  byte,  con  lo  que se obtiene 10000000 y finalmente se calcula el valor hexadecimal, que es 80.

100000002 = 8016

Independientemente de la longitud de cadena hexadecimal de la palabra de entrada, se añade 80 por la derecha.

Novatica Blockchain 241

Ahora  hay  que  añadir  a  la  cadena  una  cantidad  de bits con valor 0 hasta llegar a 448 bits  en total, que  es la longitud que abarca todos los intervalos que van desde W0 hasta W13. Cuando se hayan realizado las 64  iteraciones  SHA-256  con  los  datos  anteriores  se  ha  de  realizar  una  última operación en la que se ha de tomar cada palabra A, B, C, D, E, F , G y H de la  primera  iteración  y  realizar  una  operación  mod 232  con  su  homóloga  de  la última iteración, véase el ejemplo.

Novatica Blockchain 241

Finalmente se concatenan los valores de los 8 resultados en esta ronda 0 obteniendo el siguiente digest resultante:

502a989242bdfa912da58a972836c9cdfedd4a0278a467e00000000000000000

Para terminar, el último paso para obtener el hash  definitivo de este bloque es convertir el digest resultante a formato Little-Endian, tal y como se muestra a continuación.

0000000000000000e067a478024addfecdc93628978aa52d91fabd4292982a50

Se puede comprobar que se cumplen los requisitos del protocolo Bitcoin para el cálculo del hash  del bloque #286819 de la cadena de bloques de Bitcoin  en la red principal mainnet. Los datos empleados en la realización de este documento se pueden comprobar con los de la cadena de bloques de Bitcoin desde en cualquier explorador de bloques13.

4. Almacenamiento en ficheros

Todos los datos de los bloques que ya han sido minados se escriben en ficheros binarios con el nombre blk*.dat. Estos archivos se almacenan en diferentes directorios dependiendo del sistema operativo que tenga la computadora donde se esté ejecutando el cliente Bitcoin Core, véase la siguiente tabla:

Sistema operativo Directorio
GNU/Linux y Unix ~/.bitcoin/blocks/
MacOS ~/Library/Application Support/Bitcoin/blocks
Windows XP %APPDATA%nBitcoinnblocks
Windows Vista/7/8 C:nUsersnusernAppDatanRoamingnBitcoinnblocks

4.1. Listado y lectura de archivos

En este ejemplo se ha empleado un sistema operativo 100 % libre[7] GNU/Linux, así pues hay que posicionarse en el directorio ~/.bitcoin/blocks/. Si se listan los archivos que contiene el directorio aparecerá una lista como la siguiente:

Novatica Blockchain 241

Entre todos estos archivos los que nos interesan son los que su nombre comienza por blk seguido de unos números y terminando con la extensión .dat. Al tratarse de archivos binarios no se puede leer su contenido con un editor de textos tradicional, será necesario utilizar un programa específico para tal caso, como por ejemplo el programa hexdump[8]. Una vez abierto cualquiera de los archivos, por ejemplo el primer archivo blk00000.dat, así es como se ven los datos que contiene.

Novatica Blockchain 241

Estos son los primeros bytes del primer bloque en el primer archivo de la cadena de bloques de Bitcon, también llamado bloque  génesis. Este primer archivo no solo contiene los datos del primer bloque, hay muchos más, ordenados cronológicamente  según  se  van  minando  y  añadiendo  a  la  cadena.  Tal  y  como se explica al inicio del punto 2 de este documento, los datos de los bloques se van concatenando uno a continuación de otro.

4.2. Visualización de datos los datos en el bloque

Siguiendo con el ejemplo del bloque #286819, en condiciones normales, es decir, siempre y cuando a la cadena de bloques descargada no se le haya aplicado  algún  tipo  de  prune[9] o podado,  los  datos  se  encuentran  en  el  archivo blk00116.dat. Todos los archivos comienzan con los datos de un bloque pero los  datos  del  bloque  que  se  quiere  analizar  no  tienen  por  qué  encontrarse  en esa  posición,  es  bastante  probable  que  los  datos  comiencen  muchos  bytes  más adelante o en un offset mucho mayor desde el inicio del archivo. En este caso concreto,  los  datos  comienzan  a  partir  del  byte  número  93725126,  en  el  offset número 059621c6. En el siguiente ejemplo se ejecuta el programa hexdump con la opción -C para obtener una salida standard  por pantalla, también con la opción -s seguido del número de desde el que se quiere empezar a visualizar datos, y la opción -n para indicar el número total de bytes que se quieren mostrar, en este caso con 288 bytes es suficiente.

 

Novatica Blockchain 241

En la columna izquierda se ve el offset correspondiente a cada línea, en la parte central los datos del bloque en formato hexadecimal y la columna de la derecha cada uno de los 16 de datos representados en caracteres ASCII[10]. Se ha resaltado en diferentes colores los diferentes segmentos de datos. En color rojo aparecen los 4 que representan el dato magicID, a continuación en color verde los 4 siguientes el dato size que representa el tamaño final de este bloque. El segmento que sigue en color turquesa son los 80 que representan el header. En  color  azul  un  único  byte  que  representa  el  número  de  transacciones  registradas en el bloque y finalmente en color morado se han resaltado todos los   datos correspondientes a las transacciones del bloque.  Los datos no  terminan   en el offset 059622e6, se ha truncado el bloque en ese punto para une mejor visualización en este documento, pues la cantidad de datos del bloque mostrada en este formato podría abarcar demasiado espacio.

Referencias

1. Nakamoto, S. (2019). Bitcoin: A peer-to-peer electronic cash system. Manubot. https://bitcoin.org/bitcoin.pdf. Último acceso: 2 de abril de 2020.
2. Bitcoin Forum. https://bitcointalk.org/index.php?topic=382374.0. Último acceso: 2 de abril de 2020.
3. Wikipedia. Boolean algebra. https://en.wikipedia.org/wiki/Boolean algebra. Último acceso: 2 de abril de 2020.
4. Github. Bitcoin. https://github.com/bitcoin/bitcoin/blob/master/src/chainparams.cpp#L99. Último acceso: 2 de abril de 2020.
5. Block stream. https://blockstream.info/block/000000000000000117c80378b8da0e33559b5997f2ad55e2f7d18ec1975b9717. Último acceso: 2 de abril de 2020.
6. GitHub. JavierDominguezGomez/Cryptography. https://github.com/JavierDominguezGomez/Cryptography/blob/master/MerkleTree/merkleTree.cpp. Último acceso: 2 de abril de 2020.
7. GNU. Distribuciones libres de GNU/Linux. https://www.gnu.org/distros/free-distros.es.html. Último acceso: 2 de abril de 2020.
8. FreeBSD. Manual Pages. https://www.freebsd.org/cgi/man.cgi?query=hexdump&sektion=1. Último acceso: 2 de abril de 2020.
9. Bitcoin. Running Bitcoin. https://en.bitcoin.it/wiki/Running Bitcoin#Command-line arguments. Último acceso: 2 de abril de 2020.
10. IEEE. ASCII Code Table. https://www.ieee.li/computer/ascii.htm. Último acceso: 2 de abril de 2020.