Saltar al contenido
CrossFly es 100% open sourceSíguenos en GitHub
CrossFlyCrossFly
Empezar

Esta página fue traducida automáticamente del portugués y puede contener errores. La versión en portugués es la canónica.

Cómo usar una base SQLite cifrada

Propósito. Proteger datos sensibles en el disco con una base cifrada (vía SQLite3MC). El cifrado es opt-in: sin clave la base es un SQLite común, sin costo de cifrado. Con clave, CrossFly aplica el cifrado y valida la clave en la apertura (falla temprano, no en la primera consulta).

APIs usadas

  • SqliteDb.open(String filename, byte[] key) — abre/crea cifrado con el cifrado por defecto Sqlite.Cipher.CHACHA20 (ChaCha20-Poly1305).
  • SqliteDb.open(String filename, byte[] key, Sqlite.Cipher cipher) — abre con cifrado explícito. Opciones: CHACHA20, SQLCIPHER (AES-256-CBC + HMAC), AES128CBC, AES256CBC, RC4, ASCON128.
  • SqliteDb.rekey(byte[] newKey) — cambia la clave vía sqlite3_rekey. Pasar null o un array vacío (new byte[0]) quita el cifrado (“rekey to no key”).
  • SqliteException.code — código numérico del error. Compare con constantes de Sqlite. Clave incorrecta / el archivo no es una base ⇒ code == Sqlite.NOTADB (26). Otras útiles: Sqlite.BUSY (5), Sqlite.CONSTRAINT (19).

Cómo aparece la clave incorrecta. En el open con clave, CrossFly selecciona el cifrado, aplica la clave y hace una lectura forzada (SELECT count(*) FROM sqlite_master) para fallar inmediatamente con clave incorrecta, cerrando la conexión. Usted captura SqliteException con code == Sqlite.NOTADB.

Cuidado con el cifrado al reabrir. Para reabrir una base existente, use el mismo cifrado con el que fue creada. CHACHA20 (por defecto) solo descifra bases CHACHA20; una base SQLCIPHER necesita open(file, key, Sqlite.Cipher.SQLCIPHER).

Ejemplo completo (copiar, pegar y ejecutar)

package com.exemplo;

import java.nio.charset.StandardCharsets;

import dev.crossfly.ui.*;                     // Window
import dev.crossfly.ui.layout.*;             // VerticalLayout
import dev.crossfly.sqlite.*;                // SqliteDb, Sqlite, SqliteException

/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      byte[] key = "minha-senha-forte".getBytes(StandardCharsets.UTF_8);

      // Abrir/crear cifrado (cifra por defecto CHACHA20)
      try (SqliteDb db = SqliteDb.open("secure.db", key))
      {
         db.exec("CREATE TABLE IF NOT EXISTS secret(id INTEGER PRIMARY KEY, v TEXT)");
         db.execute("INSERT INTO secret(v) VALUES(?)", "dado sensível");

         // Cambiar la clave
         byte[] novaKey = "senha-ainda-mais-forte".getBytes(StandardCharsets.UTF_8);
         db.rekey(novaKey);
         // db.rekey(new byte[0]);  // <- removería el cifrado
      }

      // Cifra explícita (compatible con SQLCipher)
      try (SqliteDb db = SqliteDb.open("sqlcipher.db", key, Sqlite.Cipher.SQLCIPHER))
      {
         db.exec("SELECT count(*) FROM sqlite_master");
      }

      // Detectar clave errada
      try (SqliteDb db = SqliteDb.open("secure.db", "chave-errada".getBytes(StandardCharsets.UTF_8)))
      {
         // no llega aquí: la validación ya falló en el open
      }
      catch (SqliteException e)
      {
         if (e.code == Sqlite.NOTADB)          // 26 = clave errada / no es una base de datos
            System.out.println("Chave incorreta");
         else
            throw e;
      }
   }
}

El fragmento de abajo muestra solo el núcleo. Para ejecutarlo, colóquelo en el esqueleto MainWindow de arriba.

Fragmento mínimo

// verificado en la fuente: open(file,key), open(file,key,cipher), rekey, SqliteException.code == Sqlite.NOTADB
import dev.crossfly.sqlite.*;
import java.nio.charset.StandardCharsets;

byte[] key = "minha-senha-forte".getBytes(StandardCharsets.UTF_8);

// Abrir/crear cifrado (cifra por defecto CHACHA20)
try (SqliteDb db = SqliteDb.open("secure.db", key))
{
   db.exec("CREATE TABLE IF NOT EXISTS secret(id INTEGER PRIMARY KEY, v TEXT)");
   db.execute("INSERT INTO secret(v) VALUES(?)", "dado sensível");

   // Cambiar la clave
   byte[] novaKey = "senha-ainda-mais-forte".getBytes(StandardCharsets.UTF_8);
   db.rekey(novaKey);
   // db.rekey(new byte[0]);  // <- removería el cifrado
}

// Cifra explícita (compatible con SQLCipher)
try (SqliteDb db = SqliteDb.open("sqlcipher.db", key, Sqlite.Cipher.SQLCIPHER))
{
   db.exec("SELECT count(*) FROM sqlite_master");
}

// Detectar clave errada
try (SqliteDb db = SqliteDb.open("secure.db", "chave-errada".getBytes(StandardCharsets.UTF_8)))
{
   // no llega aquí: la validación ya falló en el open
}
catch (SqliteException e)
{
   if (e.code == Sqlite.NOTADB)          // 26 = clave errada / no es una base de datos
      System.out.println("Chave incorreta");
   else
      throw e;
}

Profundice

¿Te resultó útil esta página?