2016-09-14 4 views
2

J'ai un fichier de base de données dans mes actifs que je copie dans le dossier de base de données d'application. Après la copie (cela fonctionne), je veux crypter la base de données copiée avec SQLCipher.Crypter la base de données existante avec SQLCipher dans Android

Pour une raison quelconque, je reçois cette erreur:

Database: sqlite returned: error code = 26, msg = statement aborts at 5: [ATTACH DATABASE '/data/user/0/com.grandeguru.lagmeup/databases/AIRPORTS_DB.db' AS encrypted KEY 'password';] file is encrypted or is not a database

Si je regarde la base de données avec un explorateur de racine, il est toujours pas crypté et visible, donc je suppose que l'erreur est lié au fichier logique à l'intérieur de la méthode de chiffrement.

C'est le code de la classe DatabaseHelper j'ai créé, qui gère également la copie des actifs:

public class DatabaseHelper extends SQLiteOpenHelper { 

private SQLiteDatabase myDB; 
private Context context; 
public static String DB_NAME = "AIRPORTS_DB.db"; 
public static String DB_PATH = "/data/data/com.grandeguru.lagmeup/databases/"; 
public static final int DB_VERSION = 1; 


public DatabaseHelper(Context context) { 
    super(context, DB_NAME, null, DB_VERSION); 
    myDB.loadLibs(context); 
    this.context = context; 
} 

// THE ERROR IS SOMEWHERE INSIDE HERE 
public void encryptDataBase(String passphrase) throws IOException { 

    File originalFile = context.getDatabasePath(DB_NAME); 

    File newFile = File.createTempFile("sqlcipherutils", "tmp", context.getCacheDir()); 

    openDataBase(""); 

    myDB.rawExecSQL("ATTACH DATABASE '" + originalFile.getPath() + "' AS encrypted KEY '" + passphrase + "';"); 
    myDB.rawExecSQL("SELECT sqlcipher_export('encrypted');"); 
    myDB.rawExecSQL("DETACH DATABASE encrypted;"); 
    myDB.close(); 
    myDB = SQLiteDatabase.openDatabase(newFile.getAbsolutePath(), passphrase, null, SQLiteDatabase.OPEN_READWRITE); 
    myDB.close(); 
    newFile.renameTo(originalFile); 
    originalFile.delete(); 
} 

private boolean checkDataBase() { 
    File databasePath = context.getDatabasePath(DB_NAME); 
    return databasePath.exists(); 
} 


public void copyDataBase() throws IOException { 
    try { 
     File f = context.getDatabasePath(DB_NAME); 
     InputStream in = context.getAssets().open(DB_NAME); 
     OutputStream out = new FileOutputStream(f.getAbsolutePath()); 
     byte[] buffer = new byte[1024]; 
     int length; 
     while ((length = in.read(buffer)) > 0) { 
      out.write(buffer, 0, length); 
     } 
     out.flush(); 
     out.close(); 
     in.close(); 
     Log.d("copy database", "finita copia db"); 

     encryptDataBase("password"); 
    } catch (Exception e) { 
     Log.e("copy database", e.getMessage()); 
    } 

} 


public void openDataBase(String passphrase) throws SQLException { 
    String myPath = DB_PATH + DB_NAME; 
    myDB = SQLiteDatabase.openDatabase(myPath, passphrase, null, SQLiteDatabase.OPEN_READWRITE); 
} 


public void createDataBase() throws IOException { 
    boolean dbExist = checkDataBase(); 

    if (dbExist) { 
    } else { 
     this.getReadableDatabase(""); 
     try { 
      copyDataBase(); 
     } catch (IOException e) { 
      Log.e("create database", e.getMessage()); 
     } 
    } 
} 

}

Répondre

1

J'ai résolu, j'écris ma solution comme future référence. Je tout simplement de la mauvaise voie

public void encryptDataBase(String passphrase) throws IOException { 

    File originalFile = context.getDatabasePath(DB_NAME); 

    File newFile = File.createTempFile("sqlcipherutils", "tmp", context.getCacheDir()); 

    SQLiteDatabase existing_db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, "", null, SQLiteDatabase.OPEN_READWRITE); 

    existing_db.rawExecSQL("ATTACH DATABASE '" + newFile.getPath() + "' AS encrypted KEY '" + passphrase + "';"); 
    existing_db.rawExecSQL("SELECT sqlcipher_export('encrypted');"); 
    existing_db.rawExecSQL("DETACH DATABASE encrypted;"); 

    existing_db.close(); 

    originalFile.delete(); 

    newFile.renameTo(originalFile); 

} 
0

Nous avons un exemple de chiffrer une base de données SQLite texte brut dans le SQLCipher pour Android test suitehere. En outre, vous pouvez essayer d'appeler le SQLiteDatabase.loadLibs(context); statique au lieu d'essayer de l'appeler sur votre champ d'instance.

+0

Il a été une erreur de chemin, SQLCipher le faisait droit;) Maintenant, j'évolué ma classe DatabaseHelper afin de gérer une base de données non crypté (« » pass) et un mode chiffré aussi – riccardo91