2014-07-24 3 views
2

내 응용 프로그램에 기존 sqlite 데이터베이스가 있습니다. 성공적으로 실행 중입니다. 이제 sqlcipher를 사용하여 데이터베이스를 암호화해야합니다. 내 문제는 암호를 sqlite 변환 할 때 다음 예외가 있습니다. sqlite를 암호화 된 데이터베이스로 변환 :

net.sqlcipher.database.SQLiteException: table android_metadata already exists 
at net.sqlcipher.database.SQLiteDatabase.native_rawExecSQL(Native Method) 
at net.sqlcipher.database.SQLiteDatabase.rawExecSQL(SQLiteDatabase.java:1851) 
at com.x.y.convert_sqlite_to_sqlcipher(Practitioner_menu.java:2626) 
at com.x.y$AdminProcess.doInBackground(Practitioner_menu.java:1659) 
at com.x.y$AdminProcess.doInBackground(Practitioner_menu.java:1) 
at android.os.AsyncTask$2.call(AsyncTask.java:287) 
at java.util.concurrent.FutureTask.run(FutureTask.java:234) 
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
at java.lang.Thread.run(Thread.java:856) 

내 변환 코드 :

File old_sqliteFile = getDatabasePath("old_db.sqlite"); 
File databaseFile = getDatabasePath("new_db.db"); 
     databaseFile.mkdirs(); 
     databaseFile.delete(); 
    database = SQLiteDatabase.openOrCreateDatabase(databaseFile, 
        "password", null); 
database.rawExecSQL(String.format(
        "ATTACH DATABASE '%s' AS encrypted KEY '%s'", 
        databaseFile.getAbsolutePath(), "password"); 
      database.rawExecSQL("select sqlcipher_export('encrypted')"); 
      database.rawExecSQL("DETACH DATABASE encrypted"); 
      database.close(); 

사람이 내가 뭘 잘못 알아 제발 도와주세요?

+0

중복 가능성 [암호화 파일 또는 데이터베이스 (예외 net.sqlcipher.database.SQLiteException)하지 않다 (http://stackoverflow.com/questions/22062277/file-is-encrypted-or- is-not-a-database-exception-net-sqlcipher-database-sqlitee) – Gattsu

+0

@maven 질문은 거의 같지만 오류는 다르다고 생각했습니다. 어떻게 그 문제를 해결 했습니까? – Amsheer

답변

4

databaseFile을 두 번 사용하고 있습니다. openOrCreateDatabase()databaseFile이 아니라 old_sqliteFile으로 호출해야합니다.

public static void encrypt(Context ctxt, String dbName, 
          String passphrase) throws IOException { 
    File originalFile=ctxt.getDatabasePath(dbName); 

    if (originalFile.exists()) { 
     File newFile= 
      File.createTempFile("sqlcipherutils", "tmp", 
           ctxt.getCacheDir()); 
     SQLiteDatabase db= 
      SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(), 
             "", null, 
             SQLiteDatabase.OPEN_READWRITE); 

     db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';", 
            newFile.getAbsolutePath(), passphrase)); 
     db.rawExecSQL("SELECT sqlcipher_export('encrypted')"); 
     db.rawExecSQL("DETACH DATABASE encrypted;"); 

     int version=db.getVersion(); 

     db.close(); 

     db= 
      SQLiteDatabase.openDatabase(newFile.getAbsolutePath(), 
             passphrase, null, 
             SQLiteDatabase.OPEN_READWRITE); 
     db.setVersion(version); 
     db.close(); 

     originalFile.delete(); 
     newFile.renameTo(originalFile); 
    } 
    } 
+0

감사합니다. 도와 주셔서 감사합니다. – Amsheer

+0

여기에 한 가지 문제가 있습니다. 어떤 경우라도 코드 아래에서 실패했습니다. db.rawExecSQL ("SELECT sqlcipher_export ('encrypted')"); 더 이상 데이터베이스가 손상 될 수는 없습니다. 그것을 어떻게 다루는가? 이러한 코드 집합을 다시 실행하면 여전히 운이 없다. 귀하의 답변에 따르면이 http://stackoverflow.com/questions/22062277/file-is-encrypted-or-is-not-a-database-exception-net-sqlcipher-database-sqlitee 나는 이것이 손상된 줄 알았는데. – Amsheer

+0

DB가 이미 암호화되어 있는지 쉽게 알 수 있습니까? 'if (db.isEncrypted()) {db.encrypt(); }'? –

0

감사합니다, 그것은 잘 작동 : 여기

는 암호화 교체와 암호화되지 않은 데이터베이스 파일을 대체하는 방법이다. 암호를 암호화, 암호 해독 및 변경하기 위해이 코드를 추가했습니다.

@Override 
public synchronized SQLiteDatabase getWritableDatabase(String password) { 
    SQLiteDatabase sqLiteDatabase; 
    try{ 
     sqLiteDatabase = super.getWritableDatabase(password); 
    }catch(Exception e){ 
     try { 
      encrypt(context,DATABASE_NAME,PWOLD,PWNEW); 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 
     sqLiteDatabase = super.getWritableDatabase(password); 
    } 
    return sqLiteDatabase; 
} 

@Override 
public synchronized SQLiteDatabase getReadableDatabase(String password) { 
    SQLiteDatabase sqLiteDatabase; 
    try{ 
     sqLiteDatabase = super.getReadableDatabase(password); 
    }catch(Exception e){ 
     try { 
      encrypt(context, DATABASE_NAME, PWOLD, PWNEW); 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 
     sqLiteDatabase = super.getReadableDatabase(password); 
    } 
    return sqLiteDatabase; 
} 

public static void encrypt(Context context, String dbName, 
          String oldPass, String newPass) throws IOException { 
    if(!newPass.isEmpty()) Log.d(TAG,"Encrypt DB..."); 
    else Log.d(TAG,"Decrypt DB..."); 

    File originalFile=context.getDatabasePath(dbName); 

    if (originalFile.exists()) { 
     File newFile = File.createTempFile("sqlcipherutils", "tmp", 
         context.getCacheDir()); 
     SQLiteDatabase db = SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(), 
       oldPass, null, 
       SQLiteDatabase.OPEN_READWRITE); 

     db.rawExecSQL(String.format("ATTACH DATABASE '%s' AS encrypted KEY '%s';", 
       newFile.getAbsolutePath(), newPass)); 
     db.rawExecSQL("SELECT sqlcipher_export('encrypted')"); 
     db.rawExecSQL("DETACH DATABASE encrypted;"); 

     int version=db.getVersion(); 

     db.close(); 

     db = SQLiteDatabase.openDatabase(newFile.getAbsolutePath(), 
       newPass, null, 
       SQLiteDatabase.OPEN_READWRITE); 
     db.setVersion(version); 
     db.close(); 

     originalFile.delete(); 
     newFile.renameTo(originalFile); 
    } 
} 
관련 문제