Hosted on hyper.media via the Hypermedia Protocol.
Artículos
Firmas Digitales en Bitcoin - ¿Lo tuyo es tuyo?
¿Qué es la propiedad? ¿Cómo estás seguro de que algo te pertenece? ¿Cuándo lo tuyo es realmente tuyo? Antes de continuar leyendo, párate a reflexionar. … Seguro que no has encontrado una respuesta certera, ni una que cubra todas las casuísticas. ¿Sería tuya la casa que compraste sin un registro de la propiedad que lo afirme? ¿Sería tuyo el coche que compraste sin un registro donde lo hayan ligado a tu identidad? Es rara la ocasión en la que podemos decir que algo es nuestro, sin que un tercero (normalmente el Estado) avale esa afirmación. Es decir, ¿puedo decir que algo es mío sin que otro lo diga por mí? «Tu eres tú porque una autoridad central, que es el Estado, te permite tener una identidad» – 50:10 L228 – Lunaticoin Propiedad La tecnología al rescate Criptografía Asimétrica y Firmas Digitales Flujo de las Firmas Digitales Firmas Digitales aplicadas a Bitcoin ECDSA Condiciones de Gasto P2PKH Firmar en P2PKH Verificar en P2PKH Conclusión EXTRA 1: Matemática detrás de las Firmas Digitales EXTRA 2: La necesidad de un valor aleatorio k EXTRA 3: La proto-transacción EXTRA 4: Verificando Transacciones Notas Fuentes Recomendaciones Agradecimientos
17 Feb
Maleabilidad En Bitcoin
Maleabilidad: Del latín "Malleare" (Golpear con un martillo), posibilidad de un material para admitir distintas formas sin quebrarse. Una firma digital es mucho más que una simple prueba de posesión de una Clave Privada: es una declaración de intenciones. Lo que firmamos —el mensaje exacto— refleja nuestras intenciones de forma precisa. Si alguien modifica ese mensaje, cualquier observador externo podrá comprobar claramente que nuestra intención original ha sido desvirtuada. Por ejemplo, si firmamos con nuestra Clave Privada el mensaje: "Mi coche es azul", estamos declarando nuestra intención de que quien lo verifique sepa que nuestro coche es azul. Sin embargo, si alguien altera ese mensaje a "Mi coche es rojo", la verificación de la firma fallará, dejando claro que ese cambio no corresponde a nuestras intenciones originales. En Bitcoin, este principio se traduce en la firma de transacciones. Por ejemplo, podemos firmar la transacción: "Quiero transferir los fondos de las direcciones A y B hacia la dirección C." Esto refleja nuestra intención de consolidar los fondos de dos direcciones en una nueva, la dirección C. Ahora bien, ¿qué ocurre si firmamos un mensaje más general, como: "Quiero transferir los fondos de las direcciones A y B" ? En este caso, dejamos abierta la posibilidad de que alguien más complete el mensaje añadiendo, por ejemplo, "hacia la dirección D" sin que la verificación resulte en error, puesto que ese dato no está vinculado con la firma digital. Esto puede ser útil en algunos casos, pero también implica que nuestra intención original puede ser reinterpretada o moldeada por terceros. El enfoque de nuestra firma determinará qué partes de la transacción están protegidas contra modificaciones. En la mayoría de los casos, vinculamos la firma a toda la transacción, es decir, a todos los inputs (entradas) y outputs (salidas). Esto garantiza que todas las partes de la transacción sean inamovibles y cualquier alteración posterior invalide la transacción. ¿Qué pasaría si, en lugar de firmar toda la transacción, solo vinculamos nuestra firma a partes específicas, como ciertos inputs o outputs? Aunque inicialmente pueda parecer un sinsentido, esta flexibilidad que Bitcoin nos brinda para decidir que partes de la transacción se firman, nos permite crear transacciones participativas donde los individuos no están necesariamente en el mismo lugar y tiempo, aumentado el grado de personalización de las mismas. Pudiendo moldearlas a tu gusto, haciéndolas maleables. Por ejemplo, una transacción participativa sería crear un cheque al portador: Esto permite que quién posea esta transacción incompleta pueda definir posteriormente los outputs, decidiendo a dónde se enviarán los fondos. En este caso, nuestra firma desbloquea los fondos de manera correcta, dejando abierta la posibilidad de que sean gastados según el criterio del portador de ese "cheque bitcoin". Este artículo es una continuación de mi anterior artículo, y por tanto, te recomiendo encarecidamente leer "Firmas Digitales en Bitcoin - ¿Lo tuyo es tuyo?". Los indicadores SigHash y la Proto-transacción Tipos de SigHash Conclusión EXTRA: La "Chapucilla" de SigHash SINGLE EXTRA: La mejor manera de aprender: probando. EXTRA: Detalles Técnicos en la Serialización de la Proto-transacción EXTRA: Historia del Artículo Fuentes Notas: Agradecimientos:
14 Feb
Curva Elíptica En Bitcoin
Recientemente estaba ayudando a un amigo a configurar su nuevo watch-only wallet. Como era de esperar, surgió una inquietud común cuando se utiliza este tipo de monederos: “Si siempre me dices que debo mantener mis claves privadas en secreto, ¿por qué puedo ingresar mi clave pública (Nota 1) en el monedero sin poner en riesgo mis fondos?” Fue entonces cuando aproveché para explicarle el concepto de las funciones criptográficas unidireccionales. Específicamente, aquella función que conforma la base técnica para generar la clave pública: la Curva Elíptica. Tras hablar de este tema durante un buen rato, algo hizo “click” en mi mente: recordé que cuando tuve que entender el funcionamiento de la Curva Elíptica me llevo muchas horas, porque en la mayoría de las fuentes a consultar no estaba toda la información o estaba mal planteada. Además, mi amigo había sido capaz de entender el funcionamiento de la Curva Elíptica tras mi explicación en menos de 30 minutos. Es por ello, que basándome en el planteamiento que utilicé para explicarle este maravilloso concepto, fue que escribí el artículo que lees. Espero que, tras esta lectura, no tengas nunca más dudas de cómo funciona, y que siempre puedas volver para resolverlas. Comenzamos. Indagando en la Criptografía de Curva Elíptica La Criptografía de Curva Elíptica (ECC, por sus siglas en inglés) es uno de los conceptos más interesantes – e importantes – de la unión entre la Matemática y la Tecnología. Sus capacidades son muy superiores a otros sistemas con el mismo fin, y ha sido probada hasta la extenuación para probar su seguridad. En términos generales, la ECC es un tipo de función criptográfica unidireccional, es decir, permite convertir una entrada (input) en una salida (output) de tal manera que sea inviable obtener los datos de entrada original a partir de la salida. Teniendo este concepto en mente y aplicándolo a Bitcoin, ECC es esencial en un paso crucial: la derivación de la Clave Pública a partir de la Clave Privada. Sin una función unidireccional como ECC, cuando compartiésemos nuestra clave pública, nuestra clave privada se vería expuesta y, por tanto, un atacante podría obtener nuestros fondos. De ahí que sea tan necesaria una función unidireccional como ECC. Dentro de ECC existen muchas variantes de curvas elípticas y parámetros distintos. Para el caso de Bitcoin, Satoshi Nakamoto eligió la Curva Elíptica llamada “secp256k1”, una variante utilizada tanto para derivar las claves públicas como para firmar transacciones en Bitcoin. ¿Por qué eligió Satoshi a ECC? La cuestión es, habiendo múltiples funciones criptográficas que consiguen la unidireccionalidad del resultado, ¿cuál es la razón detrás de que Satoshi Nakamoto eligiese en concreto la Curva Elíptica, y no otras funciones como la RSA (Nota 2)? Si buscamos una gran seguridad a la hora de utilizar la función unidireccional, un buen nivel sería 128 bits de seguridad equivalente (Nota 3), es decir, que tenga el mismo nivel de seguridad que una clave en criptografía simétrica de 128bits. Para este nivel de seguridad, con ECC necesitamos la curva «secp256k1» que genera claves de 256 bits de longitud, mientras que con RSA necesitaríamos generar claves de 3072 bits de longitud. Es evidente que ECC es mucho más eficiente. Esto ocurre porque cuando se diseñó RSA en 1977, el problema matemático involucrado (factorización de número primos muy elevados) tenía un nivel de dificultad alto para las computadoras de ese momento. Sin embargo, con el aumento exponencial de la capacidad de cálculo, actualmente ese problema matemático es mucho más fácil de abordar. Es tal la ventaja de ECC sobre RSA, que una clave RSA de 256 bits, del mismo tamaño que las de ECC, hoy puede descifrarse en apenas 50 segundos con hardware comúnmente disponible. La diferencia tan marcada en eficiencia entre los dos sistemas es inherente al problema matemático involucrado. En RSA el nivel de complejidad es menor que en ECC, haciendo que se necesiten claves mucho más largas para lograr el mismo grado de seguridad contra ataques de fuerza bruta. Es observable que la diferencia se amplía exponencialmente conforme crece la longitud de clave necesaria. Comparativamente, la Criptografía de Curva Elíptica (ECC) se basa en operaciones matemáticas que son computacionalmente inviables de resolver incluso con las supercomputadoras actuales. Esto permite que ECC alcance altos niveles de seguridad con claves muy cortas comparado con RSA. Por lo que, con objeto de hacer más eficaz el espacio que ocupan las claves dentro de bitcoin, teniendo así un mejor equilibrio entre seguridad y tamaño, es lógico que Satoshi Nakamoto eligiera la ECC sobre la RSA. Ecuación general de la Curva Elíptica y parámetros de secp256k1 La Curva Elíptica es una función matemática que viene dada por la siguiente fórmula: y^2 = x^3+ax+b Donde a y b son parámetros que definen cada curva específica. Cada combinación de valores de a y b genera una Curva Elíptica distinta con propiedades únicas. En el caso de la Curva Elíptica secp256k1 utilizada en Bitcoin, “a” toma el valor 0 y “b” toma el valor 7. Por tanto, la ecuación queda de la siguiente forma: y^2 = x^3+7 Gráficamente, la Curva Elíptica secp256k1 presenta simetría respecto al eje x. Esto significa que, para un valor dado de x, la coordenada en y puede tomar dos valores: positivo o negativo. Esta duplicidad de valores se origina en la resolución de la ecuación que define a secp256k1 (y^2 = x^3 + 7), la cual involucra el cálculo de raíces cuadradas. Concretamente, despejando y resulta en y = ±raíz cuadrada(x^3 + 7): y^2 = x^3 + 7 \rightarrow y = \pm \sqrt{x^3 + 7} Tomando por ejemplo x = 2, se obtienen dos puntos simétricos de la forma (2, +3.87) y (2, -3.87). Cada valor de x genera así dos opciones para y, una positiva y otra negativa. La duplicidad de valores para una misma x, es una característica crucial a la hora de calcular la Clave Pública. Calculando la Clave Pública La Clave Pública se obtiene a partir de la Clave Privada y una constante G conocida como Punto Generador, la cual es estática y está definida en los parámetros de la curva secp256k1, mediante la siguiente operación: K (Clave Pública) = k (Clave Privada) · G (Punto Generador) Esta operación no se realiza sobre los números reales, sino sobre las coordenadas en la Curva Elíptica, y en ese dominio multiplicar es mejor interpretarlo como sumar tantas veces el Punto Generador como indique el valor de la clave privada. Si la Clave Privada fuera “5”, para obtener la Clave Publica habría que sumar G+G+G+G+G = 5G. Como hemos dicho antes, el Punto Generador (G) es una constante ya determinada en los parámetros iniciales de la Curva Elíptica secp256k1: 04 79be667e f9dcbbac 55a06295 ce870b07 029bfcdb 2dce28d9 59f2815b 16f81798 483ada77 26a3c465 5da4fbfc 0e1108a8 fd17b448 a6855419 9c47d08f fb10d4b8 Siendo este número en hexadecimal las coordenadas x e y en las que se posiciona el Punto Generador (G) dentro la Curva Elíptica secp256k1. Veamos esta operación de manera más visual: Imaginemos que hay que sumar los puntos “A” y “B” sobre la Curva Elíptica. Para ello trazaremos una recta que pase por ambos, y el punto donde ésta cruce de nuevo la curva, será la suma de ambos en negativo “-C”. Ahora reflejamos ese mismo punto respecto del eje x, obteniendo así el punto “C”, el cual es la suma de A y B. Y ahora consideremos como sumar un punto a si mismo, es decir, si tenemos el punto “P” queremos obtener “2P”. Para ello trazaremos una tangente al punto que queremos duplicar. Allá donde cruce la tangente, será -2P. Reflejamos -2P respecto del eje x, y obtenemos 2P. Ahora podríamos utilizar ambos métodos para, a partir de P, conseguir 3P. Esto es, 2P + P. Como se ve, podemos tomar un punto cualquiera e ir sumando y duplicando hasta conseguir la multiplicidad deseada del mismo. Apliquemos esto al Punto Generador (G). Imaginemos que se encuentra en la coordenadas (1, 2.82) y queremos obtener 5G, suponiendo que 5 es el valor de la Clave Privada. Una forma de hacerlo será duplicar G, volverlo a duplicar y finalmente sumarle la G original. Las coordenadas del punto 5G resultante serán las de la Clave Pública: 5G = (2(2G)) + G Teniendo en cuenta lo anterior, si partimos de un punto K, el cual representa las coordenadas de una clave pública, conociendo además el Punto Generador (G), ¿cuál sería el valor de la Clave Privada utilizada para obtener K? Es imposible determinarlo, ¿verdad? Esta es la gracia de la Curva Elíptica, lo que da razón a su existencia. El único método para encontrar el multiplicador (la Clave Privada) partiendo del Punto Generador y la Clave Pública, sería a través de fuerza bruta, esto es, probar cada número de entre todos los posibles hasta dar con aquel que multiplicado por el Punto Generador nos devuelve la Clave Pública (y todo esto siendo operaciones sobre la Curva Elíptica, las cuales requieren de un mayor procesamiento.) En el caso de Bitcoin, la Clave Privada no es un numero de un solo dígito, sino un número que se representa con 256 bits, es decir, puede estar entre 0 y 115792089237316195423570985008687907853269984665640564039457584007913129639936 Si tuviéramos acceso a 1.000.000 de ordenadores como el ordenador más potente que se encuentra en nuestro país, el MareNostrum4, necesitaríamos nada más y nada menos que 24478287087205351645436112169940788908514621232681 años para tener probabilidades de acertar una clave específica que se adecuase a los requerimientos de la Curva Elíptica, o lo que es lo mismo:  1773788919362706640973631316662376007863 edades del universo (13800 millones de años). Como dirían en mi tierra: “Ahí es na’ ”. He aquí la magia de la Criptografía mediante Curva Elíptica, es muy fácil ir en un sentido (derivar la Clave Pública) y virtualmente imposible ir en el contrario.  Queda asegurada de esta forma la unidireccionalidad de la derivación de la clave pública y la robustez de este sistema. Eficiencia en el Formato Una vez hemos obtenido la Clave Pública a partir de la Clave Privada, nos encontramos con un número tal que así: 04 becf1cf6 ef544238 89aca536 44398f14 fd6e9531 bd01980a 38e6c7b2 ca3fb426 6efd97cb 9392ed18 6761526d 20630327 59b122e1 79be6fb8 bf3575ec e29d3621 Siendo “04” un prefijo que denota el tipo de formato de la Clave Pública, en azul la coordenada en x y en rojo la coordenada en y. Sin duda es un número bastante largo, que cuando es transmitido por la red, ocupa mucho espacio. ¿Y si pudiéramos reducirlo a la mitad? Recuerda, que la Curva Elíptica viene definida por la función: y^2 = x^3+7 Y que, por tanto, podemos despejar y solo conociendo x. Es decir, podemos comprimir el espacio que ocupa la Clave Pública, eliminando la parte que ocupa la y, dejando solo la x. Cuando se necesite conocer la Clave Pública, el ordenador en cuestión despejará y, obteniendo así ambas coordenadas. Muy fácil, ¿no? Pues todavía queda un detalle: Cuando se almacena la Clave Pública solo con la coordenada x, se denomina “Comprimida”. En este caso, para identificarla, lleva como prefijo “02” si la coordenada y es positiva, o “03” si es negativa. Esta distinción del signo de y mediante el prefijo es necesaria para resolver adecuadamente la ecuación de la Curva Elíptica secp256k1. Esto es debido a que involucra la resolución de una raíz cuadrada, por ende, para cada x válido existirán dos posibles puntos sobre la curva, (x, +y) o (x, -y), simétricos respecto al eje x. Es decir, indicar el signo de y permite identificar de forma inequívoca al punto sobre la curva que representa la clave pública correspondiente a una determinada clave privada. Por ejemplo, esta es la Clave Pública de unas líneas más arriba, ya comprimida, con el prefijo 03 indicando que su coordenada y es negativa. Pues comprobar que la coordenada x, la que se mantiene, tiene el mismo valor que antes. 03 becf1cf6 ef544238 89aca536 44398f14 fd6e9531 bd01980a 38e6c7b2 ca3fb426 De esta forma se logra reducir el tamaño de la representación de la clave pública a la mitad en comparación a almacenar ambas coordenadas, sin que se pierda en ningún momento la información necesaria para verificar transacciones. Esto optimiza su almacenamiento y transmisión cuando se realiza una transacción, resultando en menores costes en fees. Conclusión A la hora de construir el sistema de propiedad que rige en Bitcoin, Satoshi sin duda eligió sabiamente la Curva Elíptica secp256k1: sus características singulares permiten asegurar nuestra Clave Privada y, por ende, nuestros fondos. Gracias a la ECC podemos compartir nuestra Clave Pública con un watch-only wallet sin temer a que obtengan la Clave Privada, dado que sencillamente imposible. Eso sí, si compartimos nuestra Clave Pública, pueden ver las transacciones que realizamos quedando nuestra privacidad afectada, aunque este tema lo dejo para otro día. Gracias por llegar hasta aquí. Abajo dejo un apunte adicional para los más frikis (como yo) y un listado de las fuentes principales utilizadas para preparar este artículo. --- EXTRA: Nube de Puntos A nivel más técnico, la Curva Elíptica secp256k1 no se define sobre el plano cartesiano como previamente había mostrado para simplificar, sino sobre un Campo Fp con p igual a (2^256 – 2^32 – 2^9 – 2^8 – 2^7 – 2^6 – 2^4 – 1), un número primo muy alto. La Curva Elíptica sobre el Campo Fp luce tal que así: Este campo Fp se construye a partir de elementos obtenidos como el resto de dividir un número (la coordenada x e y de cada punto de la curva en el plano cartesiano) por p. Al realizar esta operación, cuando se grafican los nuevos puntos, pasan de ser una línea continua a una nube de puntos. A pesar de esta conversión, la Curva Elíptica mantiene las propiedades que explicábamos anteriormente: Existe simetría con respecto al eje x, así como se puede trazar una línea entre dos puntos para sumarlos Con fines ilustrativos, en el gráfico he empleado el valor de p = 43.5 para que se pueda observar claramente como se conforma la nube de puntos. Puedes probar ha modificar el valor de P, así como el rango de los valores de X y el tipo de Curva Elíptica por tu cuenta, cambiando los valores de la variable “parameters” en el código de Python que he preparado «elliptic-curve-field-p-chart.py»: https://github.com/SalvaZaraes/bitcoin --- Notas Fuentes
14 Feb
Entradas al blog
Si haces Vulnerables tus bitcoin, no llores cuando alguien se los lleve
En Bitcoin, normalmente bloqueas tus fondos de tal manera que solo pueden ser gastados si aportas una firma digital válida que se vincula a todas las partes de la transacción (te voy adelantando que mejor que sea así). Sin embargo, en Bitcoin también puedes gastar tus fondos aportando una firma digital que no se vincula a todas las partes de la transacción o incluso puedes gastarlos sin utilizar firmas digitales si así fue definido en el script de bloqueo de los fondos. En ambos casos, esto puede dar lugar a situaciones en las que tus bitcoin son como un billete de 50€ abandonado en plena calle y al alcance de cualquiera. Es decir, no es que te los estén robando, sino que nunca los protegiste correctamente. Para evitar que esto te ocurra, he listado posibles situaciones en las que tus fondos bitcoin se harían vulnerables: 1. SINGLE|ANYONECANPAY con Qty Input > Qty Output 2. SINGLE|ANYONECANPAY con nInputs > nOutputs 3. NONE con un solo input 4. NONE|ANYONECANPAY 5. P2SH con puzzles y retos como scripts Conclusión Notas
14 Feb
Hash-Preimage para una transacción con múltiples inputs
En el artículo sobre las Firmas Digitales, en el apartado técnico, dejé un pequeño detalle sin tratar: ¿Qué sucede con la proto-transacción cuando hay más de un input? ¿De qué manera se firma una transacción si cada input tiene su propia clave privada? Antes de nada, hay que tener en cuenta el importante rol del "SigHash". El "SigHash" nos indica que partes de la transacción se firman digitalmente. Normalmente se firma toda la transacción para que sea imposible modificar cualquiera de sus partes; pero en otras ocasiones, solo se firma una parte concreta de la transacción, permitiendo que se puedan aportar mas fondos (añadir nuevos inputs) o se pueda determinar a donde van los fondos (modificar los outputs). Aunque suena raro, estas funcionalidades son muy utilizadas, sobre todo en transacciones colaborativas. Como decía, normalmente se firma digitalmente toda la transacción, lo que se indica con el "SigHash ALL". Si intentas reconstruir la proto-transacción (sobre la cual se generan las firmas) en una transacción que tenga múltiples inputs (SigHash ALL), siguiendo el mismo enfoque que para una transacción de un solo input (también SigHash ALL), la verificación de las firmas digitales resultará en error. Este error ocurre porque, en una transacción con múltiples inputs, cada uno corresponde a una clave privada distinta, y al firmar con cada clave cabría esperar que la proto-transacción mantuviera la misma estructura. Sin embargo, en lugar de utilizar la misma proto-transacción para todas las firmas, el proceso sigue una lógica algo particular: Es decir, para cada input, la proto-transacción que se ha firmado con la clave privada correspondiente es distinta. ¿Por qué se diseñó de esta forma? Puede haber varias razones: optimizar el proceso de firma, prevenir errores o evitar que scripts incorrectos sean firmados involuntariamente... aunque la verdad nunca la sabremos: Ask Satoshi Puedes probar a verificar las firmas digitales de una transacción "SigHash ALL" con múltiples inputs P2PKH y P2PK (y cualquier cantidad de outputs de cualquier tipo), con el siguiente código que he preparado: Además, con la función getPreimage(índice*), el código te devolverá la proto-transacción (preimage) sobre la que se firmó ese input en cuestión. *El índice corresponde al input deseado: 0 para el primer input, 1 para el segundo, y así sucesivamente. **Proto-transacción = Hash-Preimage
14 Feb