Cuando Falla la Matemática: Dentro de la Vulnerabilidad de Entropía de COLDCARD

Análisis técnico del bug de RNG que presuntamente debilitó la autocustodia de Bitcoin — y por qué la autocustodia sigue siendo innegociable

Qué Pasó

El 30 de julio de 2026, Coinkite publicó un aviso de seguridad advirtiendo que un bug en el firmware de COLDCARD había debilitado la entropía de las frases semilla generadas en dispositivos afectados. El equipo de Ingeniería y Seguridad de Bitcoin de Block publicó simultáneamente un análisis técnico identificando la causa raíz.

El informe de Block incluye una declaración contundente: “active exploitation is under way” (explotación activa en curso). Usuarios han perdido Bitcoin. Esto no es teórico.

La causa raíz: un bug sutil en una directiva del preprocesador hizo que la generación de semillas de wallet usara un PRNG de software no criptográfico llamado Yasmarang en lugar del generador de números aleatorios verdadero (TRNG) de hardware STM32 que COLDCARD estaba diseñado para usar.

La Analogía

Imagina que la llave de tu casa no se corta de una llave en blanco aleatoria, sino que se genera a partir de dos datos: el número de serie impreso en el cerrojo de tu puerta (visible para cualquiera que se acerque) y el milisegundo exacto en que giraste la llave por primera vez.

En el bug de COLDCARD, el “número de serie del cerrojo” es el UID del chip — un identificador de fábrica grabado en cada microcontrolador STM32 al fabricarlo. Es fijo de por vida, legible desde la memoria, y parcialmente transformado en el número de serie USB del COLDCARD. El “milisegundo en que giraste la llave” es el contador SysTick — un timer de hardware que cuenta hacia atrás desde un valor fijo en cada ciclo de reloj y se reinicia cada milisegundo. En el momento en que Yasmarang se inicializa, captura el valor actual de SysTick y le aplica XOR con el UID.

Si alguien conoce ambos valores — o puede acotarlos a un rango suficientemente pequeño — puede fabricar una llave idéntica. No necesita romper ningún cifrado. Solo necesita repetir la misma aritmética que el dispositivo ejecutó. Eso es lo que pasó aquí, pero para llaves privadas de Bitcoin.

Yasmarang: Cuando un PRNG de Juguete Reemplaza a un TRNG de Hardware

El código fuente muestra que MicroPython incluye un PRNG de software como fallback para MCUs sin RNG de hardware. Se llama Yasmarang, y nunca fue diseñado para uso criptográfico.

El Algoritmo

El estado interno de Yasmarang son solo cuatro variables: pad (32 bits), n (32 bits), d (32 bits), y dat (8 bits). Se inicializa una sola vez:

pad = *(uint32_t*)MP_HAL_UNIQUE_ID_ADDRESS ^ SysTick->VAL;  // UID del chip XOR timer
n   = RTC->TR;   // registro de tiempo del RTC
d   = RTC->SSR;  // subsegundos del RTC
dat = 0;

// Cada llamada posterior:
pad += dat + d * n;
pad  = (pad << 3) + (pad >> 29);   // rotación de 3 bits
n    = pad | 2;
d   ^= (pad << 31) + (pad >> 1);
dat ^= (char)pad ^ (d >> 8) ^ 1;
return pad ^ (d << 5) ^ (pad >> 18) ^ (dat << 1);  // 32 bits de salida

Por Qué Es Catastrófico

1. Estado minúsculo y no criptográfico. El estado inicial proviene del UID del chip (un identificador de fábrica, no un secreto), el contador SysTick (~80,000 valores posibles en Mk2/Mk3), y los registros del RTC (correlacionados con la hora de arranque, potencialmente estáticos en cold boot). Eso no es entropía — es metadata del dispositivo y timing.

2. Sin reseed. Después de la inicialización, nunca se mezcla nueva entropía. Cada salida es una función determinística del estado inicial. Conoces el estado → reproduces el stream completo.

3. Operaciones no criptográficas. Shifts, XORs y sumas simples no son un cifrado. Un CSPRNG como HMAC-DRBG resistiría la predicción incluso con conocimiento parcial del estado. Yasmarang no ofrece esa garantía.

4. El SHA256d al final no ayuda. La generación actual de wallets hashea los 32 bytes de salida del RNG con SHA256d. Pero el hash determinístico no puede aumentar el número de entradas posibles. Si hay solo 232 salidas posibles del RNG, hay como máximo 232 semillas posibles, independientemente del hash.

Propiedad CSPRNG (ej. HMAC-DRBG) Yasmarang
Estado interno 256+ bits ~104 bits (no aleatorios)
Fuente de entropía TRNG de hardware, reseed periódico UID + timer, una vez
Resistencia a predicción Computacionalmente inviable Trivial si se conoce el estado
Reseeding Periódico desde TRNG Nunca (o 32 bits en Mk4)
Estándar NIST SP 800-90A Ninguno

El Bug de #ifndef vs #if

La regresión entró en marzo de 2021, cuando COLDCARD migró sus operaciones de curva elíptica a libsecp256k1 de Bitcoin Core. La generación de semillas de wallet pasó de ckcc.rng_bytes() (que usaba el TRNG de hardware) a ngu.random.bytes() (que resolvió a Yasmarang).

El Bug del Preprocesador

El código de libngu verificaba la disponibilidad del RNG de hardware con:

#ifndef MICROPY_HW_ENABLE_RNG
#error "get a HW TRNG plz"
#endif

#ifndef verifica si el macro está definido — no si su valor es nonzero. La configuración de board de COLDCARD lo definía como:

#define MICROPY_HW_ENABLE_RNG (0)

El macro está definido — su valor es 0. #ifndef lo ve como “definido” y no dispara el #error. La compilación continúa. Pero como el valor es cero, MicroPython compila su fallback Yasmarang en lugar del RNG de hardware.

La Verificación Correcta

#if !MICROPY_HW_ENABLE_RNG
#error "get a HW TRNG plz"
#endif

#if evalúa el valor. Si es 0, !0 es verdadero, y el #error se dispara. La compilación falla. El desarrollador se da cuenta.

Por Qué Este Patrón Es Peligroso Más Allá de COLDCARD

Este no es un error exclusivo de Coinkite. Es un patrón que afecta a cualquier codebase C/C++ que mezcla verificaciones #ifdef con definiciones de macros numéricos:

Definición del macro #ifdef / #ifndef #if ¿Detecta valor 0?
#define FOO definido #if FOO → 0 (falso) N/A
#define FOO 1 definido #if FOO → 1 (verdadero)
#define FOO 0 definido #if FOO → 0 (falso) #ifndef falla aquí

En C embebido, es común definir features como 0 o 1 en lugar de definido/no-definido. Si una librería verifica con #ifdef mientras la config de board define como 0, el guard pasa silenciosamente.

Lecciones para Revisión de Código

  • Nunca mezcles #ifdef con valores numéricos. Si defines como 0/1, usa siempre #if. Si quieres verificar existencia, usa #ifdef.
  • Establece una convención por proyecto. O todo es booleano (#define FOO 0/1, verifica con #if FOO) o existencial (#define FOO o nada, verifica con #ifdef FOO).
  • Agrega verificación de símbolos en build-time. El fix de COLDCARD ahora excluye explícitamente el objeto fallback de MicroPython y agrega un check que falla la compilación si rng_get() no viene del board.
  • Verifica reachability end-to-end, no solo presencia. El código del TRNG estaba en el binario — simplemente no se llamaba desde el path de generación de semillas. La revisión existente confirmó que el código estaba ahí, pero nunca verificó qué implementación de rng_get() el call path realmente alcanzaba.

Este bug pertenece a una categoría más amplia que ha causado algunas de las peores vulnerabilidades de la historia:

  • Heartbleed (OpenSSL, 2014): el bounds check existía en una rama que no se tomaba
  • goto fail (Apple, 2014): un goto duplicado saltaba la validación del certificado
  • COLDCARD (2026): el TRNG estaba en el binario pero la resolución de símbolos tomaba el fallback

La lección común: la presencia de código seguro en el binario no prueba que el runtime lo use. La verificación debe ser reachability end-to-end, no solo presencia.

Espacio de Búsqueda: ¿Cuántos Candidatos?

El análisis de Block proporciona estimaciones detalladas de espacio de búsqueda para cada dispositivo afectado:

Mk2/Mk3 v4.0.0–4.1.9

Estos dispositivos no tienen reseed criptográfico. Si el atacante conoce el UID del dispositivo, estado de timers e historial de llamadas RNG:

  • Timers conocidos: 20 candidatos — determinístico. La semilla se puede reproducir exactamente.
  • SysTick desconocido (UID conocido): ~80,000 valores ≈ 216.3
  • UID_low32 XOR SysTick completamente desconocido: como máximo 232
  • Límite superior amplio (todos los timers independientes): ~240.7

¿Cómo Podría un Atacante Obtener el UID, el Estado de Timers y el Historial de Llamadas?

Ninguno de estos valores es un secreto criptográfico. Pueden obtenerse o acotarse a través de varios canales realistas:

  • UID del dispositivo (32 bits bajos): El UID del STM32 es un identificador de fábrica, no un secreto. Es legible desde la memoria del chip y se transforma parcialmente en el número de serie USB del COLDCARD. Si el atacante tuvo acceso físico al dispositivo — aunque sea brevemente — o si la víctima publicó una foto del dispositivo mostrando el número de serie, o si el número fue registrado por un host USB comprometido, los 32 bits bajos del UID pueden ser recuperables. Incluso sin el valor exacto, el atacante puede acotarlo a un rango pequeño basándose en el lote de fabricación del dispositivo.
  • Valor de SysTick: SysTick es un contador periódico que se reinicia cada milisegundo. En Mk2/Mk3 tiene ~80,000 valores posibles. Pero el atacante no necesita probar los 80,000 — puede perfilar la secuencia de boot en su propio dispositivo idéntico. El boot del firmware toma un número aproximadamente predecible de ciclos de reloj antes de la primera llamada al RNG. Midiendo esto en un Coldcard propio del mismo modelo, puede acotar la ventana de SysTick a un rango mucho menor. Si el RTC de la víctima era estático o cero durante cold boot (lo que el análisis de Block sugiere probable en Mk2/Mk3), SysTick se convierte en la variable principal, y 80,000 candidatos es una búsqueda trivial.
  • Historial de llamadas RNG: El número de veces que se llamó rng_get() antes de la generación de la semilla determina la posición en el stream de Yasmarang. En la práctica, la secuencia de boot es determinística — el mismo firmware ejecuta los mismos pasos de inicialización en el mismo orden. El atacante puede reproducir esto en su propio dispositivo y determinar el conteo exacto de llamadas antes de la generación del seed. Si la víctima realizó operaciones adicionales que consumen RNG (generar un paper wallet, tiradas de dados que aún llamaron al PRNG, etc.), el atacante puede necesitar enumerar algunos offsets plausibles, pero esto multiplica el espacio de búsqueda por una constante pequeña, no por un factor exponencial.

La clave: ninguno de estos valores es un secreto. Son metadata del dispositivo e información de timing. El atacante no necesita romper ningún cifrado — solo necesita repetir la misma aritmética que el dispositivo ejecutó en el boot.

Mk4/Q/Mk5

Estos dispositivos añaden un reseed del secure element en el boot, pero solo 32 bits de entropía llegan al estado del PRNG:

  • Estado fallback conocido + historial de llamadas: como máximo 232 streams de salida distinguibles
  • Enumeración promedio: ~231 candidatos
  • Límite superior amplio (timers independientes + reseed): ~273.3
Costo práctico — Mk4, Q, y Mk5 (con reseed exitoso): A ~100M derivaciones BIP32/seg en una GPU moderna, 231 candidatos promedian ~21 segundos. 232 son ~43 segundos. Estos modelos tienen como máximo 232 semillas posibles, así que todo el espacio de búsqueda se agota en menos de un minuto en una sola GPU. Para Mk2/Mk3 v4.0.0–4.1.9, si el atacante conoce el UID y el RTC era estático durante cold boot, el espacio se reduce a ~80,000 candidatos (solo SysTick) — agotable en milisegundos en CPU. Si todos los timers son desconocidos, el límite amplio es ~240.7, aún factible en un cluster de GPUs en horas a días.

Cómo una Dirección Pública se Convierte en un Oráculo de Validación

El ataque no requiere acceso al dispositivo de la víctima ni a sus llaves privadas. Solo requiere una pieza de información pública: cualquier dirección Bitcoin que se sepa pertenece al wallet de la víctima.

La razón: cada dirección Bitcoin se deriva de una llave pública, que se deriva de la semilla a través de paths de derivación BIP-32. Dada una semilla candidata, el atacante puede derivar determinísticamente la misma secuencia de direcciones que el wallet produciría. Si alguna dirección derivada coincide con una dirección conocida de la víctima, la semilla candidata es correcta.

¿De dónde vienen estas direcciones conocidas?

  • Transacciones on-chain: Cada transacción Bitcoin es pública. Si la víctima alguna vez recibió o envió Bitcoin, sus direcciones son permanentemente visibles en la blockchain. Un atacante monitoreando la blockchain puede recolectar direcciones asociadas a un xpub específico.
  • Direcciones de depósito en exchanges: Si la víctima envió Bitcoin desde su COLDCARD a un exchange, la dirección de envío está on-chain y es rastreable.

Una vez que el atacante tiene una sola dirección conocida, el ataque es cómputo puro: generar semilla candidata → derivar path BIP-32 → derivar dirección → comparar. Repetir 232 veces para Mk4/Q/Mk5, o tan solo 80,000 veces para Mk2/Mk3 con timers conocidos. El oráculo nunca toca el dispositivo de la víctima.

Tabla Resumen

Dispositivo / Firmware Atacante conoce timers Límite con timers ocultos
Mk1; Mk2/Mk3 hasta v3.2.2 ~2256 ~2256
Mk2/Mk3 v4.0.0–4.1.9 20 <240.7
Mk4/Q/Mk5 (reseed exitoso) ≤232 <273.3
Mk4/Q/Mk5 (sin reseed)* 20 <241.3

* Path condicional; la falla ordinaria de secure element en producción parece detenerse en lugar de continuar.

Dispositivos Afectados — Tabla Completa

Dispositivo Firmware al generar semilla Estado
Mk1 Todos hasta v3.0.6 No afectado (fuera de la regresión)
Mk2 Hasta v3.2.2 No afectado (usa TRNG de hardware)
Mk2 v4.0.0–4.1.9 Afectado — sin reseed seguro
Mk3 Hasta v3.2.2 No afectado (usa TRNG de hardware)
Mk3 v4.0.0–4.1.9 Afectado — sin reseed seguro
Mk4 Producción v5.0.0 en adelante (antes de 5.6.0) Afectado — reseed de 32 bits
Q Toda la producción (antes de 1.5.0Q) Afectado — reseed de 32 bits
Mk5 Toda la producción (antes de 5.6.0) Afectado — reseed de 32 bits
TAPSIGNER / OPENDIME / SATSCARD Todos No afectado (codebase diferente)

Versiones de Firmware Corregidas

Modelo Firmware corregido
Mk3 4.2.0 o posterior
Mk4/Mk5 (Standard) 5.6.0 o posterior
Mk4/Mk5 (Edge) 6.6.0X o posterior
Q (Standard) 1.5.0Q o posterior
Q (Edge) 6.6.0QX o posterior
Actualizar el firmware NO repara un seed existente. Si tu semilla se generó con firmware afectado, debes generar una semilla nueva en el dispositivo actualizado y migrar tus fondos. La única excepción: si ingresaste 50+ tiradas de dado independientes y privadas al crear la semilla, los dados aportan ≥128 bits de entropía por sí solos y la semilla no está comprometida por este bug.

Timeline Técnico

  • 28 de enero, 2021: El guard vulnerable de libngu para STM32 existe.
  • 1 de marzo, 2021: COLDCARD migra la generación de wallets a libngu.
  • 17 de marzo, 2021: Firmware v4.0.0 incluye el path vulnerable.
  • 11 de marzo, 2022: Se agrega la API de reseed de 32 bits y el reseed de boot del Mk4.
  • 14 de marzo, 2022: Primer Mk4 de producción v5.0.0 incluye el reseed.
  • 30 de julio, 2026: Block y otros investigadores notan reportes de usuarios perdiendo fondos. Se encuentra la causa raíz.
  • 31 de julio, 2026: Firmware corregido disponible para todos los modelos afectados.
  • 3 de agosto, 2026: La comunidad reporta que el hotfix introduce un bug de recuperación del TRNG que puede brickear dispositivos. PR #692 y #693 propuestos.

IA como Arma de Doble Filo

El firmware de Coinkite siempre ha sido de código abierto. El análisis de Block asume que alguien usó IA para revisar el código público del firmware y descubrió el bug antes que Coinkite.

El detalle más revelador: Coinkite también usó uno de los mejores modelos de IA disponibles para revisar su código en busca de problemas de seguridad — y no encontró este bug.

“Both attackers and defenders have the same AI tools, but today it did not help us, and only helped the bad guys.”
— Coinkite

Esto es “No confíes, verifica” en su forma más cruda. El código abierto no es magia — requiere verificación activa, no transparencia pasiva. El código fue público por más de cinco años. El bug estuvo ahí todo el tiempo. Tomó un atacante con herramientas de IA para encontrarlo.

El Hotfix que Brickea: Un Nuevo Bug en el Fix

El 31 de julio de 2026, Coinkite publicó el firmware hotfix que reemplazó Yasmarang por el TRNG de hardware. El fix era correcto en dirección — rng_get() ahora resuelve al TRNG de hardware del board en lugar del fallback de software. Pero introdujo un bug nuevo que puede brickear el dispositivo permanentemente.

Qué Pasa

El TRNG de hardware del STM32 puede experimentar “seed errors” transitorios — glitches temporales causados por fluctuaciones de voltaje, cambios de temperatura, o ruido eléctrico en el chip. Son eventos normales de hardware, no fallas permanentes. El manual de referencia (RM0432 §25.3.7) documenta el procedimiento de recuperación: limpiar el flag de error SEIS, luego togglear RNGEN off y on.

El código del hotfix no implementa esta recuperación. Cuando ocurre un seed error:

  1. El flag SEIS se queda pegado (latched) y DRDY deja de señalizar
  2. RNGEN sigue activo, así que rng_init() considera el periférico “bien” y no hace nada
  3. Cada llamada subsequente a rng_get() hace timeout a los 10ms y lanza OSError(EFAULT)
  4. Esto persiste para siempre — a través de reboots de la capa Python

Por Qué Brickea el Dispositivo

Después del hotfix, rng_get() se llama desde el shuffle del orden de escaneo del teclado — la rutina anti-Tempest que aleatoriza el orden en que se escanean las teclas. Esto corre desde un callback de interrupción a hasta 60 Hz, antes del login. Cada keypress triggers 3+ lecturas del TRNG.

Si cualquiera de esas lecturas golpea el estado de fallo del TRNG:

  • OSError propaga a die_with_debugshow_fatal_error + show_logout
  • El usuario ve una pantalla de error fatal
  • No puede ingresar su PIN
  • No puede alcanzar el menú de upgrade
  • El dispositivo queda brickeado

Esto coincide con reportes reales de usuarios cuyos Coldcards quedaron “atascados en pantalla de error / no bootea” después de instalar el hotfix.

La Ironía

Antes del hotfix, Yasmarang (el PRNG de software) no podía fallar — siempre producía output, aunque fuera débil. Después del hotfix, el TRNG de hardware sí puede fallar transitoriamente, pero el código no tiene path de recuperación. El fix reemplazó un generador que nunca se caía por uno que puede brickear el dispositivo con un glitch aleatorio de hardware.

Estado Actual

Dos PRs de la comunidad abordan esto:

  • PR #692 (Silexperience210): propone rng_reset() para limpiar flags de error y rehabilitar el periférico, con 3 intentos antes de fallar. También envuelve el shuffle del keypad en try/except para que un fallo de RNG degrade la higiene anti-Tempest en lugar de brickear el login. Solo preventivo — no puede recuperar dispositivos ya brickeados.
  • PR #693 (scgbckbone, colaborador de Coldcard): un fix alternativo. El colaborador dijo “I think I have something better here.”

Ningún PR se ha mergeado aún. Si no has instalado el hotfix, espera a un firmware que incluya el fix de recuperación del TRNG. Si ya lo instalaste y tu dispositivo funciona, evita generar seeds nuevas con el TRNG del dispositivo — usa el método de solo dados descrito abajo.

El Workaround de Solo Dados

Si necesitas generar una semilla nueva y tu única opción es una Coldcard, puedes bypassar ambos bugs por completo:

  1. En tu Coldcard, ve a: New Wallet → Advanced → Dice Rolls
  2. Tira un dado físico de 6 caras 99 veces mínimo (idealmente 100+)
  3. Ingresa cada tirada manualmente en el dispositivo
  4. La Coldcard hashea la secuencia de dados directamente para generar la semilla
  5. Este path no usa Yasmarang ni el TRNG de hardware — los dados son la única fuente de entropía

Con 99+ tiradas de un dado justo, obtienes ~256 bits de entropía (≥128 bits con 50+ tiradas). Este método está documentado oficialmente por Coinkite y bypassa tanto el bug de Yasmarang como el bug de brickeo del hotfix. La secuencia de dados es material de llave secreta — nunca la fotografíes, la guardes digitalmente, ni la ingreses en una computadora conectada a internet.

Resumen de decisión para usuarios de Coldcard:

No has actualizado: Genera seeds nuevas con 99+ tiradas de dado. Espera a un firmware que incluya tanto el fix de Yasmarang COMO el fix de recuperación del TRNG antes de actualizar.

Actualizaste y el dispositivo funciona: NO generes seeds nuevas usando el TRNG del dispositivo. Si necesitas una seed nueva ahora, usa solo dados. Espera al próximo firmware estable.

Actualizaste y el dispositivo se brickeó: Los PRs actuales son preventivos, no curativos. Contacta a soporte de Coinkite.

Seed creada con 50+ tiradas de dado: Tu seed está SEGURA de esta vulnerabilidad. No necesitas migrar por este bug.

Cómo Verificar si Tu Seed Está Afectada

Paso 1: Identifica Tu Modelo y Firmware

En tu COLDCARD, navega a:

Advanced → Upgrade → Current Firmware Info

Anota el modelo exacto (Mk2, Mk3, Mk4, Mk5, Q) y la versión de firmware.

Paso 2: La Pregunta Crítica

El firmware que tenías cuando generaste la semilla es lo que importa. Actualizar hoy no repara retroactivamente una semilla generada con firmware vulnerable. Compara el modelo de tu dispositivo y la versión de firmware que tenías al generar la semilla contra la tabla “Dispositivos Afectados — Tabla Completa” más abajo. Si tu semilla se generó en cualquier combinación de modelo/firmware marcada como afectada, necesitas migrar a una semilla nueva.

Paso 3: Verifica la Excepción de los Dados

Si usaste “Add Dice Rolls” con 50+ tiradas independientes y privadas al crear tu semilla, tu semilla no está comprometida por este bug — los dados aportan ≥128 bits de entropía por sí solos.

Paso 4: Verifica Tu Passphrase

Un passphrase BIP-39 (no el PIN del COLDCARD) añade una barrera independiente. Si usaste uno fuerte y único, proporciona cierta protección — pero de todos modos debes migrar a una semilla nueva.

Paso 5: Si Estás Afectado, Migra

Advertencia sobre el firmware hotfix del 31 de julio: Las versiones de firmware corregido publicadas el 31 de julio de 2026 (Mk3 4.2.0, Mk4/Mk5 5.6.0, Q 1.5.0Q, y sus equivalentes Edge) introducen un bug separado que puede brickear tu dispositivo si el TRNG de hardware experimenta un glitch transitorio. Ve la sección “El Hotfix que Brickea” arriba para detalles. Espera a un firmware que incluya tanto el fix de Yasmarang COMO el fix de recuperación del TRNG antes de instalar cualquier actualización.

Si tu semilla está afectada y necesitas migrar, tienes varias opciones:

Opción A: Generar una semilla nueva en tu Coldcard usando solo dados

Puedes crear una semilla segura incluso con firmware afectado — sin actualizar — usando el método de solo dados. Esto bypassa tanto Yasmarang como el TRNG por completo:

  1. En tu Coldcard, ve a: New Wallet → Advanced → Dice Rolls
  2. Tira un dado físico de 6 caras 99 veces mínimo (idealmente 100+)
  3. Ingresa cada tirada manualmente en el dispositivo
  4. La Coldcard hashea la secuencia de dados directamente para generar la semilla — sin RNG
  5. Con 99+ tiradas obtienes ~256 bits de entropía (≥128 bits con 50+ tiradas)

Este método está documentado oficialmente por Coinkite. La secuencia de dados es material de llave secreta — nunca la fotografíes, la guardes digitalmente, ni la ingreses en una computadora conectada a internet.

Opción B: Mover fondos a una hardware wallet de otro fabricante

Si tienes acceso a una hardware wallet de un fabricante diferente que genera entropía correctamente, puedes migrar tus fondos ahí:

  • Trezor Model T / Safe 5: Usa un TRNG de hardware con firmware de código abierto. También permite añadir entropía con dados durante la generación de la semilla.
  • BitBox02: Usa un TRNG de hardware (STM32) con firmware de código abierto.
  • SeedSigner: Un signer air-gapped DIY que permite generar semillas con tiradas de dados o fotos de entropía. Totalmente de código abierto.
  • Krux: Otro dispositivo air-gapped DIY que soporta generación de semillas con dados. De código abierto.

Siempre verifica que el dispositivo que elijas genere entropía desde un TRNG de hardware, e idealmente que soporte entrada de entropía externa (dados). Investiga el historial del dispositivo y si su firmware es de código abierto.

Opción C: Mover fondos temporalmente a una hot wallet

Si no tienes acceso a una segunda hardware wallet y necesitas mover tus fondos rápido, puedes enviarlos a una hot wallet como medida temporal:

  • Usa una wallet de móvil o escritorio de reputación (ej. Blue Wallet, Electrum, Sparrow Wallet)
  • Genera una semilla nueva en la hot wallet — estas usan el CSPRNG del sistema operativo, que es criptográficamente sólido
  • Mueve los fondos ahí temporalmente hasta que puedas adquirir una hardware wallet con generación de entropía adecuada
Una hot wallet no es una solución permanente. Las hot wallets están conectadas a internet y son vulnerables a malware, keylogging, y ataques de red. Úsala solo como puente, no como almacenamiento a largo plazo. Mueve a una hardware wallet lo antes posible.

Independientemente de la opción que elijas:

  1. Anota y verifica el nuevo backup, fingerprint de wallet, y una dirección de recepción
  2. Envía una transacción de prueba pequeña y confirma que llega
  3. Mueve el resto de los fondos
  4. Conserva el backup viejo hasta que la migración esté completa y confirmada
Migra con calma. Apresurar una migración de wallet crea un riesgo más inmediato que la vulnerabilidad que intentas resolver. Verifica cada paso.

Usa un Passphrase — Siempre

Ya sea que uses una hot wallet o una cold wallet, un passphrase BIP-39 es altamente recomendable. Un passphrase (no el PIN del dispositivo) crea un wallet separado encima de tu frase semilla. Incluso si un atacante recupera tu semilla, no puede acceder a tus fondos sin el passphrase.

  • Usa un passphrase fuerte y único — no una palabra del diccionario, no una cita, no algo reutilizado
  • Guarda el passphrase por separado de las palabras semilla
  • Cada passphrase produce un wallet válido — verifica el fingerprint del wallet antes de depositar fondos
  • Perder el passphrase significa perder acceso a ese wallet permanentemente

Un passphrase añade una capa independiente de seguridad que te protege incluso si la entropía de la semilla es débil. No es sustituto de entropía adecuada, pero eleva significativamente la barrera para un atacante.

Resumen de Decisión

¿Semilla generada en Mk2/Mk3 v4.0.0–4.1.9?       → AFECTADA, migra
¿Semilla generada en Mk4/Mk5/Q antes del fix?          → AFECTADA, migra
¿Usaste 50+ dados al crear la semilla?                 → SEGURA por esta vulnerabilidad
¿Semilla generada en firmware anterior a v4.0.0?        → SEGURA
¿Tu dispositivo es TAPSIGNER / OPENDIME / SATSCARD?    → NO AFECTADO

OPCIONES DE MIGRACIÓN (elige una):
  A) Semilla nueva en Coldcard con 99+ tiradas de dado (funciona en firmware afectado)
  B) Mover a una hardware wallet de otro fabricante (Trezor, BitBox02, etc.)
  C) Mover temporalmente a una hot wallet (Electrum, Sparrow, Blue Wallet)

NO instales el hotfix del 31 de julio hasta que salga un firmware
con fix de recuperación del TRNG — puede brickear tu dispositivo.

USA SIEMPRE un passphrase BIP-39, hot o cold wallet.

La Lección Mayor: La Autocustodia Sigue Siendo Imperativa

Algunos usarán este incidente para argumentar que la autocustodia es peligrosa. Es exactamente lo contrario.

Los exchanges son hackeados, congelan cuentas, y colapsan — FTX, Celsius, BlockFi son solo ejemplos recientes. Cuando no es tu llave, no es tu Bitcoin. Este bug se encontró, se documentó públicamente, y se parchó — porque el código era abierto y la comunidad pudo auditarlo. Intenta exigir ese nivel de transparencia a un exchange centralizado.

La autocustodia es imperativa. Pero requiere responsabilidad activa:

  • Verifica tu versión de firmware
  • Considera añadir entropía con dados al generar semillas
  • Mantén backups verificados
  • Migra con calma cuando se descubren vulnerabilidades, no con pánico
  • Usa multisig con quorums de dispositivos independientes y seguros

“Sé tu propio banco” no es un eslogan — es un compromiso con la seguridad que nadie más puede asumir por ti.

El bug estuvo en el código por más de cinco años. El código era abierto. Nadie lo encontró hasta que un atacante lo hizo. Esa es la realidad de la seguridad de código abierto: la transparencia es necesaria pero no suficiente. Habilita la verificación — no la reemplaza.

La autocustodia sigue siendo la única forma de ser verdaderamente soberano sobre tu Bitcoin. Este incidente no cambia eso. Lo refuerza.


Referencias