Estándar ECDSA en Bitcoin

Elliptic-Curve-E-0-7-Real-Number

Tal como se describe en el whitepaper, Bitcoin usa el concepto de firma digital criptográfica para asegurar la legitimidad de las operaciones de transmisión de valor entre participantes en la red:

ECDSA

En la implementación de Bitcoin se determinó el uso del estándar de firma ECDSA o Elliptic Curve Digital Signature Algorithm. ECDSA es un estándar que puede funcionar con diferentes curvas elípticas que han demostrado ser seguras hasta la fecha. Para Bitcoin se escogió la curva secp256k1. Dicha curva está profusamente tratada en la wiki oficial de BitcoinSV.

La relación matemática y criptográfica entre nuestras claves privada y pública es:

  • k == private key (es un número entero)
  • P == public key , es un punto (x,y) de la curva elíptica que se calcula P = kG
  • (x,y) cumplen la función y^2 ≡ x^3 + 7 (mod p ), con p constante, número primo que acota el valor máximo de cualquier número entero válido.

G es el punto generador característico de la curva de secp256k1. Tanto G como p son constantes en secp256k1.

La base de la fortaleza criptográfica es que la clave pública P = k * G se puede calcular usando algoritmos conocidos de multiplicación ECC, pero es muy costoso o lento calcular k = P / G (la clave privada).

Ejemplo de pareja de claves pública y privada

Cojamos una clave privada k cualquiera (k=2) y veamos que la clave pública está sobre la curva, es decir, que la multiplicación ECC respeta la curva.

  • k = 2 (clave privada trivial y poco segura, no recomendable)
  • P = 2G, teniendo que P = (x,y) un punto sobre la curva.

Para nuestra clave privada k = 2, los valores que se obtienen son (formato hexadecimal)

x = c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5
y = 1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a

Vamos a comprobar que tanto P (pública) como G (punto generador) están sobre la curva con unos sencillos cálculos en Python:


% Constantes en secp256k1
Gx = int("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16)
Gy = int("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",16)
p = int("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",16) 

%%  y^2 ≡ x^3 + 7 (mod p)
print ((Gx * Gx  * Gx % p) + 7 == Gy*Gy %p)
% -> Devuelve True

%Ahora comprobamos P, nuestra clave pública
x = int("c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",16)
y = int("1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a",16)

print ((x * x  * x % p) + 7 == y * y % p)
% -> Devuelve True

Descubriendo claves públicas en la blockchain

Las transacciones coinbase del principio de la cadena de bloques tenían el scriptPubKey de tipo “pubkey”. Eso significa que tenemos las claves públicas en formato SEC no comprimido en el mismo script. Por ejemplo, miremos el bloque 12345. El scriptPubKey contiene la clave pública (destacada en negrita) como la yuxtaposición de las coordenadas x e y. Nuevamente en formato hexadecimal:

4104c5d62274610e82819939c3341a4addc72634664d73b11ba761de42839aa3496f93b3b3ee80e497eb5a68439b02f04e9aeb1604fbcaa074aa82f0f7574f9f110dac

Si le aplicamos nuestro código python de arriba debe salir que x e y cumplen la función elíptica. Queda como ejercicio para el que lo quiera comprobar.

4 Likes