Recuperar una base de datos de Signal dañada

Signal Desktop guarda todo tu historial de mensajes en una única base de datos SQLite, pero está envuelta en cifrado SQLCipher, así que una herramienta normal solo ve texto cifrado. El camino de vuelta a tus mensajes tiene dos pasos: descifrar db.sqlite localmente con la clave que ya está en tu equipo y luego ejecutar un rescate de páginas al estilo .recover sobre el archivo en texto plano; nada de esto exige subir el archivo más sensible que posees.

Tu archivo nunca sale de tu dispositivo — la reparación ocurre en tu navegador. 0 bytes subidos.

Your data is the big block — usually intact. What breaks is the small index. Repair rebuilds it.

Suelta un archivo aquí o exploraToca para elegir un archivo

ZIP · Office · PDF · vídeo · JPG · PNG · RAR/7z · SQLite — reparados aquí mismo, en tu navegador. No se sube nada

0 bytes subidosGratis: 3 reparaciones/día — hasta 500 MB de vídeo, 100 MB de documentos y archivos, 50 MB de fotos. Descarga gratuita. Una reparación 5,90 €. Sin cuenta.

Repáralo ahora

  1. Suelta el archivo
  2. La reparación ocurre en local
  3. Descarga el resultado

Signal Desktop almacena todo tu historial de mensajes en una única base de datos SQLite llamada db.sqlite, pero no es SQLite sin más: Signal usa SQLCipher, una bifurcación que cifra de forma transparente todo el archivo con AES-256, cabecera incluida. Eso significa que un motor de rescate de páginas (este incluido) solo ve ruido de alta entropía y responde file is not a database hasta que el archivo se descifra. Por eso recuperar una base de datos de Signal rota son dos pasos: primero descifrarla localmente con la clave que ya está en tu equipo, produciendo un archivo SQLite en texto plano; luego suelta ese archivo arriba y la herramienta recorre sus páginas en tu navegador y reconstruye una base de datos limpia con cada fila que aún pueda decodificar. Tanto la clave como los datos se quedan en tu dispositivo.

El db.sqlite de Signal está cifrado: descífralo antes de cualquier rescate

La base de datos de Signal Desktop reside en ~/Library/Application Support/Signal/sql/db.sqlite en macOS, en %AppData%\Signal\sql\db.sqlite en Windows y en ~/.config/Signal/sql/db.sqlite en Linux. Como SQLCipher cifra el archivo entero, ejecutar file db.sqlite muestra bytes aleatorios en lugar de la habitual firma SQLite format 3\0. Cualquier herramienta SQLite normal —el intérprete sqlite3, DB Browser o el motor de rescate de esta página— ve texto cifrado, no páginas, y no puede ni va a adivinar la clave.

La clave SQLCipher de 64 caracteres hexadecimales está en config.json, junto a la base de datos. En las versiones antiguas se guarda en claro bajo un campo key; desde 2024 Signal la envuelve bajo encryptedKey usando la API safeStorage de Electron, respaldada por el elemento del Llavero de macOS llamado "Signal Safe Storage", por DPAPI en Windows y por gnome-libsecret / kwallet en Linux. Como la envoltura está atada a tu cuenta del sistema operativo, la clave se desenvuelve en la misma máquina y el mismo usuario que la crearon.

Con la clave en bruto ya disponible, abre la base de datos en cualquier herramienta compatible con SQLCipher (el CLI sqlcipher, o una compilación de DB Browser for SQLite construida con SQLCipher) y ejecuta PRAGMA key = "x'<clave-64-hex>'"; seguido de PRAGMA cipher_compatibility = 4; — Signal incorpora SQLCipher 4. Luego exporta una copia en texto plano con .recover o con VACUUM INTO 'plain.sqlite'. Ese archivo en texto plano es el que sueltas aquí. Trabaja siempre sobre una copia byte a byte, nunca sobre tu único original.

Qué significa "malformed" dentro de una base de datos de Signal

Una vez descifrada, una base de datos de Signal es un archivo SQLite corriente: un array plano de páginas de tamaño fijo (4096 bytes cada una). La página 1 contiene la cabecera y el esquema; cada tabla e índice es un árbol B de páginas interiores que apuntan hacia abajo, a páginas hoja que guardan las filas. Los datos de Signal viven en tablas como messages (cada fila identificada por id, con conversationId, sent_at, received_at, type, una columna body y una columna json que lleva el registro completo del mensaje), conversations, reactions, sessions, items y un índice de texto completo messages_fts (FTS5) usado para las búsquedas.

La corrupción casi siempre es localizada. Un corte de corriente a mitad de una escritura, una sincronización interrumpida, una página rota en un almacenamiento que mintió sobre el vaciado: un solo puntero de un árbol B deja de concordar con los datos y SQLite lanza SQLITE_CORRUPT: Error: database disk image is malformed (11). Rechaza el archivo entero en cuanto no puede fiarse de la estructura, aunque tus demás tablas sigan intactas en sus páginas hoja. El archivo parece mucho peor de lo que está.

El error relacionado file is not a database (SQLITE_NOTADB, código 26) tiene aquí dos significados: o bien la firma de 16 bytes de la cabecera se dañó (las páginas que hay detrás suelen estar intactas), o —mucho más habitual con Signal— apuntaste una herramienta normal al archivo todavía cifrado. Si lo ves antes de descifrar, es el cifrado hablando, no un daño.

Qué recupera el rescate de páginas de una BD de Signal, y qué no

El rescate de páginas no arregla el archivo roto en su sitio; hace lo mismo que el propio .recover de SQLite. Recorre el archivo descifrado página por página y, por cada página que parece una hoja de tabla, lee cada celda directamente —rowid, tipos seriales, valores— y vuelve a insertar cada fila decodificable en una base de datos nueva y vacía. Las páginas dañadas se omiten; las páginas legibles entregan sus filas sobreviva o no el árbol B que las indexaba. Las filas que la cadena de punteros ya no alcanza se encuentran mediante un barrido en bruto, y las filas cuya tabla de origen no se puede identificar van a una tabla lost_and_found indexada por página y celda, en lugar de descartarse. En la práctica, tus filas de messages vuelven con su body y su json intactos aunque lo que se rompiera fuera el índice FTS o el árbol de una sola conversación.

Si el fallo dejó un archivo hermano -wal (el modo WAL prepara las transacciones confirmadas más recientes antes de volcarlas —checkpoint— a db.sqlite), ahí están tus mensajes más nuevos, pero también está cifrado con SQLCipher, así que descífralo junto con el archivo principal. Dada una base de datos en texto plano y su WAL en texto plano, el motor superpone los fotogramas confirmados antes del escaneo para que la recuperación refleje la última transacción confirmada.

Los límites honestos son reales. Los adjuntos no están en la base de datos: Signal guarda las fotos, los vídeos y los archivos como blobs separados y cifrados individualmente bajo attachments.noindex/, así que una fila de messages recuperada conserva el puntero y los metadatos, pero rescatar la BD no descifra el propio archivo multimedia. Todo lo que se haya sobrescrito o truncado físicamente al final del archivo se ha perdido: un archivo SQLite no tiene redundancia con la que reconstruirlo. Y la salida recuperada es siempre sospechosa: como el escaneo lee celdas en bruto, incluidas las páginas de la freelist, pueden reaparecer mensajes borrados y un valor puede volver con la clase de almacenamiento equivocada, así que verifícala contra una fuente conocida y fiable antes de depender de ella.

Por qué esto pertenece a tu propia máquina

La base de datos de un mensajero es el único archivo que menos querrías en un servidor que no controlas: es cada conversación, cada contacto y cada grupo que has conservado. Los servicios de "reparación" basados en subidas copian ese archivo a una infraestructura que no puedes inspeccionar, bajo unas condiciones de retención que tú no redactaste; y con una base de datos de Signal, eso desmonta en silencio todo el sentido de usar Signal.

Aquí el rescate se ejecuta por completo en la pestaña de tu navegador: el archivo en texto plano se lee del disco, se reconstruye localmente y se descarga, y puedes abrir la pestaña Red (Network) y ver cómo salen 0 bytes. Igual de importante: el paso de descifrado también se queda en local —tu clave SQLCipher sale de tu propio Llavero (o de config.json) y la usa una herramienta de tu máquina, nunca se transmite—. Recuperar una base de datos de Signal así significa no confiar a ningún tercero ni los datos ni la clave.

Qué puede y qué no puede reparar

Puede reparar

  • Una base de datos de Signal que has descifrado a texto plano (con sqlcipher o una compilación de DB Browser con SQLCipher) y que luego indica "database disk image is malformed"
  • Filas de messages —la columna body y el registro json completo— extraídas de las páginas hoja del árbol B que sobrevivieron
  • conversations, reactions y otras tablas cuando una sola página o puntero defectuoso tumbó todo el archivo
  • Filas que la cadena de punteros no alcanza, mediante un escaneo de páginas en bruto, con las filas no atribuibles colocadas en una tabla lost_and_found
  • Los mensajes más nuevos desde un archivo hermano -wal descifrado, superpuestos antes del escaneo

No puede reparar

  • El propio db.sqlite todavía cifrado: descífralo primero en local; el motor rescata SQLite en texto plano, no texto cifrado de SQLCipher
  • Cualquier cosa sin la clave: un encryptedKey que no puedes desenvolver (Llavero perdido, otra máquina u otro usuario) nunca se convierte en SQLite legible
  • Los adjuntos de los mensajes: viven como archivos cifrados por separado bajo attachments.noindex/, no dentro de la base de datos
  • Mensajes sobrescritos o truncados físicamente al final del archivo: ninguna herramienta puede inventarlos
  • Una garantía de exactitud: pueden reaparecer filas borradas y cambiar los tipos; verifica los datos recuperados antes de depender de ellos

Si una reparación falla, te decimos por qué (datos que faltan frente a estructura dañada), y nunca se te cobra por una reparación fallida.

Preguntas frecuentes

¿Puede esta herramienta descifrar mi db.sqlite de Signal por mí?

No: es un rescate de páginas en texto plano, no un descifrador. El db.sqlite de Signal está cifrado con SQLCipher, así que primero lo descifras localmente con tu propia clave (en el CLI sqlcipher o en una compilación de DB Browser con SQLCipher, usando PRAGMA key = "x'…'" y PRAGMA cipher_compatibility = 4) y luego exportas una copia en texto plano con .recover o VACUUM INTO. Suelta aquí ese archivo en texto plano. Tanto la clave como los datos permanecen en tu máquina todo el tiempo.

¿Dónde guarda Signal la clave y por qué necesito config.json?

La clave SQLCipher de 64 caracteres hexadecimales se guarda en config.json, junto a la base de datos. Las versiones antiguas la mantienen en claro bajo un campo key; desde 2024 Signal la envuelve bajo encryptedKey con la safeStorage de Electron (elemento del Llavero de macOS "Signal Safe Storage", DPAPI en Windows, libsecret/kwallet en Linux). Como esa envoltura está atada a tu cuenta del sistema, solo puedes desenvolver la clave en la misma máquina y el mismo usuario que crearon la base de datos.

Signal dice que el database disk image está malformed. ¿Está todo perdido?

Casi nunca. Ese mensaje es SQLITE_CORRUPT (código de resultado 11): SQLite siguió un puntero y topó con una página que no es una página de árbol B válida, así que rechaza el archivo entero. El daño suele limitarse a una página y a lo que cuelga de ella en un único árbol B; el resto de tus messages, conversations y demás tablas sigue intacto en sus páginas hoja, que es justo lo que extrae un recorrido de páginas.

¿Volverán también mis fotos y archivos?

No desde la base de datos. Signal guarda los adjuntos como archivos separados y cifrados individualmente bajo attachments.noindex/; la base de datos solo contiene punteros y metadatos hacia ellos. Recuperar la BD te devuelve las filas de los mensajes y sus referencias, pero los blobs multimedia se descifran aparte a partir de la clave maestra: rescatar la base de datos no descifra los archivos en sí.

¿Se sube mi base de datos de Signal para repararla?

No. El archivo descifrado se lee de tu disco y se reconstruye en la pestaña de tu navegador; no se transmite nada, y puedes confirmar que salen 0 bytes en la pestaña Red (Network). Eso importa más en la base de datos de un mensajero que en casi cualquier otro archivo —es todo tu historial de conversaciones— y el paso de descifrado también se queda en local, así que tu clave SQLCipher nunca se envía a ningún sitio.

Relacionado: Reparar una base de datos SQLite dañada · Reparar un libro de Excel · Verifica que no se sube nada