Firma bitcoin

14 febrero 201729 mayo 2017

Jaime Núñez Miller, socio fundador de Bankabit y de Zentank y veterano de la comunidad Bitcoin firma este anexo para explicar el proceso de la firma en bitcoin y los distintos procedimientos utilizados para realizarlo. Estamos seguro que estos apuntes añadidos al capítulo firmado por Jaime (“Criptografía y consenso aplicado a la blockchain”) ayudarán al lector del libro a tener una visión más amplia y complementaria de uno de los elementos más sofisticados dentro de la tecnología Blockchain: el proceso de la firma.

***

Las firmas electrónicas en general funcionan obteniendo primero el hash del mensaje o del dato que queremos firmar y después cifrando ese hash con una clave privada. Ahora ya tenemos dos cosas: el mensaje y el hash cifrado. Ese hash cifrado es a lo que llamamos firma.

Después, quien quiera verificar la firma realiza el proceso inverso para comprobar que la firma es correcta. Obtiene el hash del mensaje y lo comparará con el resultado de descifrar la firma. Si son idénticos la firma es correcta.

En las firmas ECDSA el proceso es algo más complejo y lo hemos analizado en este otro anexo. No se comparan directamente el hash y el resultado de descifrar la firma, sino que se aplican fórmulas que utilizan el hash y varios puntos en la curva elíptica (el Generator Point, un punto aleatorio). El resultado que se compara para saber si la firma es válida es sólo un punto en la curva elíptica elegido de forma aleatoria en el momento de la firma.

En general una transacción consiste en un mensaje que traspasa el control de un token de una dirección a otra. En el protocolo Bitcoin, por ejemplo, las direcciones son en realidad una clave pública. En concreto el hash de esa clave. Quien tenga después el control, es decir, la clave privada, a su vez podrá firmar una transacción haciendo lo mismo. Una transacción es sólo un mensaje, al igual que un correo electrónico, pero con una estructura distinta. Las transacciones las hemos tratado ya en detalle en el libro. Por eso, en este anexo explicaremos sólo lo necesario para entender el proceso de la firma.

Una transacción debe:

  1. Indicar qué tokens quiero transferir. Para ello incluyo en el mensaje el ID de una o varias transacciones anteriores y los tokens que quiero transferir.
  2. Aportar los datos requeridos por la anterior transacción para desbloquear esos tokens e incluirlos en mi nueva transacción.
  3. Definir qué datos tendrá que aportar quien quiera volver a desbloquearlos y usarlos en el futuro.

Se puede considerar que las transacciones simplemente cambian las condiciones que se exigen para gastar uno o varios tokens, o dicho de otra forma, son una función para cambiar el estado (las condiciones de desbloqueo) de los tokens. Cualquiera que pueda desbloquearlos será el “propietario” de los mismos.

Esas condiciones de desbloqueo de las que hablamos se formulan incorporando en cada Output una sencilla ecuación de forma que cualquiera que aporte el dato para resolverla podrá usar esos tokens y en consecuencia crear un nuevo Output en la nueva transacción. Por ejemplo, los datos necesarios para desbloquear un Output en una transacción típica Bitcoin son dos:

  • Una clave pública.
  • La firma ECDSA de los demás datos de la transacción (firma que se hace usando la clave privada correspondiente a la dirección de ese Output).

Así pues, quien quiera gastar esos bitcoins deberá firmar los datos de la transacción (del mensaje) e incorporar después la firma y la clave pública a la transacción. Serán tantas firmas y claves públicas como oOutputs.

Una vez creada la transacción con todos los datos necesarios se envía por Internet en donde será recogida por los nodos de la red P2P. Todo este proceso evidentemente se suele hacer mediante una aplicación wallet. Los nodos verificarán la validez de la transacción y en especial comprobarán que las firmas son correctas. El proceso de verificación tiene dos fases:

  1. Verificar la firma
    1. Se hace aplicando el algoritmo de verificación de firma ECDSA
  2. Comprobar la dirección
    1. Obtener la dirección bitcoin que corresponde a la clave pública.
    2. Confirmar que la dirección corresponde con la del Output de entrada.

El algoritmo de firma ECDSA

Las firmas ECDSA son algo más complejas que lo que se muestra en el gráfico simplificado al comienzo de este apartado. Un mayor detalle del funcionamiento se puede consultar en el siguiente apartado. Con el algoritmo podemos hacer dos cosas:

  1. Firmar una transacción, lo que produce una firma que se pone en la primera parte del Signature script del Output entrante.
  2. Verificar esa firma con la clave pública que se encuentra también en ese Signature script, lo que servirá para validar la transacción.

 

Firmar una transacción

 

Para firmar una transacción el wallet debe obtener tres puntos en la curva elíptica.

 

  1. Message Point. Se calcula el hash de la transacción (txHash) y se multiplica por el Generator Point de la curva elíptica.(Message Point) = txash * G
  2. Random Point. Es un punto aleatório(Random Point) = Número aleatorio * G

    El Random Point tiene coordenadas (x,y). De este punto sólo usaremos la coordenada x a la que llamaremos r, También necesitaremos el Número aleatorio que hemos usado y al que llamamos Rn.

 

  1. Random PubKey Point. Este punto lo obtenemos multiplicando r (la coordenada x del Random Point) por la Clave Pública (K).(Random PubKey Point) = r * K

A continuación debemos hallar un valor llamado Signature factor (s) usando los datos anteriores y la clave privada (k) mediante la siguiente fórmula:

 

Signature factor = s = (txHash + r * k) / Rn mod n

 

La firma constará de estos dos valores:

  • r (coordenada x del Random Point)
  • s (Signature Factor)

que se incluyen en el Signature script de la transacción.

 

Verificar una firma

Para verificar una firma los nodos tendrán que dar los siguientes pasos.

 

  1. Sacar el Hash de la transacción (txHash) y dividirlo por el Signature Factor.V1 = txHash / s

 

  1. Dividir r por s 

    V2 = r / s

 

  1. A continuación habrá que obtener el Random Point usando el Generator Point (G) y la Clave Pública (K) con la siguiente fórmulaRandom Point = V1 * G + V2 * K

 

Si la coordenada x de este Random Point coincide con entonces la firma es válida.

 

Este proceso es seguro por varios motivos:

 

  • Dada una Clave Pública (K), es imposible crear un Signature factor (s) válido sin conocer el Generator Point (G).
  • El Signature Factor se obtiene con el Hash de la transacción, por lo que si el mensaje cambia, el Signature Factor ya no servirá para obtener el Random Point.

 

Sin embargo, toda la seguridad depende de la capacidad del wallet para no generar por error el mismo número aleatorio para dos transacciones distintas. Si se diera ese caso entonces las ecuaciones que hemos visto se podrían emplear para descubrir la clave privada.