El barrido duró 41 minutos

El 30 de julio alguien recorrió 1.196 direcciones de bitcoin y las vació, llevándose 1.082,65 bitcoines, por valor de unos 70,2 millones de dólares, en una ventana de 41 minutos. Nadie forzó una cerradura. No se tocó ningún dispositivo, no se engañó a ningún usuario, no se vulneró ningún servidor. El atacante no necesitó nada de eso, porque las claves privadas que protegían esas direcciones podían deducirse desde cero. Los primeros informes situaron la pérdida cerca de 38 millones de dólares; cuando los investigadores terminaron de contar, la cifra rozaba el doble.

Los dispositivos implicados eran monederos físicos Coldcard fabricados por Coinkite, precisamente la categoría de producto que se compra para mantener las claves lejos de las redes. Eso es lo que hace que el incidente merezca una hora de atención de cualquier propietario, piense lo que piense del bitcoin. El fallo no ocurrió en el perímetro que todo el mundo presupuesta. Ocurrió en el momento en que se creó el secreto, años antes de que nadie intentara robarlo.

Una macro puesta a cero activó el sustituto

El relato técnico de la propia Coinkite es inusualmente franco sobre el mecanismo. En marzo de 2021, durante una migración a libsecp256k1 de Bitcoin Core, la generación de semillas pasó de la rutina que invocaba el generador de números aleatorios por hardware del dispositivo a una función de propósito general. Esa nueva ruta se resolvía hacia el sustituto por software de MicroPython en lugar de hacia la implementación por hardware de Coldcard. El código sustituto existía desde mayo de 2018 y nunca había tocado la generación de semillas hasta aquella migración.

El motivo de que llegara a compilarse merece copiarse en su propia lista de revisión. La guarda que rodeaba al sustituto comprobaba si una macro de configuración estaba definida, no si estaba puesta a uno. Los desarrolladores la habían puesto a cero, entendiendo que allí no hacía falta el generador por hardware, y una macro puesta a cero sigue siendo una macro definida. La guarda leyó la presencia del valor en lugar del valor mismo, y encendió el sustituto. Nadie escribió criptografía débil. El generador por hardware existía y funcionaba. Simplemente dejó de ser aquello de lo que se extraía la semilla.

Pasaron cinco años y todas las pruebas seguían en verde

En dispositivos Mk2 y Mk3 con firmware 4.0.1 a 4.1.9, las semillas resultantes llevaban unos 40 bits de entropía en vez de los 128 que debería tener una frase de doce palabras. En Mk4, Mk5 y Q el panorama era mejor pero no seguro: los ingenieros habían mezclado valores de los elementos seguros en el estado del generador como, en palabras de Coinkite, una reserva de la reserva, lo que elevó esas semillas hasta unos 72 bits. Ambas cifras son catastróficas del mismo modo. El azar no se ve. Una clave con 40 bits detrás firma transacciones, verifica direcciones y se restaura desde una copia igual que una de 128, de modo que todas las pruebas funcionales que la empresa y sus clientes ejecutaron durante cinco años se superaron, con razón, mientras el producto estaba roto.

Coinkite ofrece además un detalle que la mayoría de los proveedores habría enterrado. Hace unas semanas, escribe, la empresa usó uno de los mejores modelos de inteligencia artificial disponibles para revisar su código en busca de problemas de seguridad, y no encontró este fallo. Conviene detenerse ahí antes de que el próximo proveedor le diga que un modelo ha revisado su código. El defecto no era sutil visto en retrospectiva ni estaba oculto, pero vivía en la juntura entre una configuración de compilación y una suposición criptográfica, que es justo la costura que un revisor que lee buscando calidad de código difícilmente tratará como una frontera de seguridad.

La corrección protege la próxima clave, no la anterior

Coinkite publicó firmware corregido el 31 de julio para cada modelo y rama afectados: 4.2.0 para Mk2 y Mk3, 5.6.0 para Mk4 y Mk5, 1.5.0Q para Q y las compilaciones edge correspondientes. Después publicó la frase que pesa más que el parche. Actualizar el firmware no cambia ni repara una semilla existente. La instrucción de la empresa es instalar el firmware corregido, generar una semilla nueva en el dispositivo actualizado, anotar y verificar su copia de seguridad antes de depositar nada, confirmar una nueva dirección de recepción en la pantalla del dispositivo, enviar una pequeña transacción de prueba y solo entonces mover el resto de los fondos.

Eso es una migración, no una actualización, y en esa distinción está toda la lección. Dos cosas podían salvar un monedero creado en la ventana afectada: cincuenta tiradas de dados independientes y privadas introducidas mediante la función de dados del propio dispositivo, ya que Coldcard las incorporaba a la semilla, o una contraseña larga fuerte y única, que actúa como barrera separada delante de la semilla débil. Aun así, Coinkite recomienda migrar cuanto antes incluso a quienes la usaron. TAPSIGNER, OPENDIME y SATSCARD funcionan sobre bases de código distintas y no están afectados.

Inventaríe lo generado, no solo lo que ejecuta

Casi todo proceso de parcheo que un propietario haya aprobado trata la versión del software como unidad de riesgo. Se descubre que una versión es vulnerable, se actualiza y la exposición termina. Los defectos de entropía rompen ese modelo por completo, porque el daño no está en el código en ejecución sino en artefactos que el código emitió y le entregó: claves, tokens, identificadores de sesión, códigos de recuperación, secretos de API, certificados. Esos objetos sobreviven a la versión que los creó, viajan a copias de seguridad y a sistemas de terceros, y arrastran la debilidad de forma permanente. Actualizar el generador detiene la producción de secretos malos. No hace nada con el inventario.

Así que la pregunta para cualquier proveedor cuyo producto cree secretos en su nombre no es solo qué versiones están afectadas. Es qué secretos se generaron con una versión afectada, cómo se enumeran y cuál es la vía de rotación. Eso vale mucho más allá de los monederos físicos: el HSM de la pila de pagos, la autoridad de certificación, la línea de aprovisionamiento de dispositivos, el proveedor de identidad que emite tokens de larga duración. Allí donde una máquina acuña algo de lo que usted dependerá después, la ventana defectuosa es lo que hay que inventariar, y casi nadie lleva registro de ella.