如果你的app要使用一個的本地數據庫,而數據庫的安全又很重要,那么,你就需要加密它,而且是在打包前就加密:
因為apk就是一個壓縮包,如果你在app安裝的時候,才去加密數據庫,對不起,別人已經從apk中解壓出來未加密的數據庫。
接下來,我們來看看,如何使用sqlcipher給本地數據庫加密,並提取出來(我寫的只是一種很low的方法,但是真實有效):
0、導包
compile 'net.zetetic:android-database-sqlcipher:3.4.0@aar'
1、首先,我們把要未加密的數據庫放在項目中
\SqlEncrypt\app\src\main\res\raw\my_database.db
2、接下來,我們來看下java代碼,也就是MainActivity
package com.xxx.sqlencrypt; import android.content.Context; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import net.sqlcipher.database.SQLiteDatabase; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; public class MainActivity extends AppCompatActivity { private String TAG = "MainActivity"; private String baoName = "com.xxx.sqlencrypt"; File dbFile = new File("/data" + Environment.getDataDirectory().getAbsolutePath() + "/" + baoName + "/databases/"); String dbPath = "/data" + Environment.getDataDirectory().getAbsolutePath() + "/" + baoName + "/databases/my_database.db";// 要把你Raw文件的db保存到sdcard中 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initPublicDB(); // 初始化數據庫 try { encrypt(this,"my_database.db","123456"); // 加密數據庫 } catch (IOException e) { e.printStackTrace(); } } /** * 加密函數 * 來源:https://www.jianshu.com/p/3baf311f8c8c */ public void encrypt(Context ctxt, String dbName, String passphrase) throws IOException { File originalFile = ctxt.getDatabasePath(dbName); // 獲取數據庫路徑 if (originalFile.exists()) { // 判斷數據庫是否存在 Log.i("SSS","db yes"); }else { Log.i("SSS","db no"); } if (originalFile.exists()) { File newFile = File.createTempFile("sqlcipherutils", "tmp", ctxt.getCacheDir()); SQLiteDatabase.loadLibs(getApplicationContext()); 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); } } /** * 初始化數據庫 */ private void initPublicDB() { if (!dbFile.exists()) { // 如果文件夾不存在,則創建新的文件夾 dbFile.mkdirs(); } if (!(new File(dbPath).exists())) { //判斷數據庫文件是否存在,若不存在則執行導入,否則直接打開數據庫 Log.v(TAG, "導入數據庫到/" + baoName + "/databases/"); InputStream is = getResources().openRawResource(R.raw.my_database); // 要導入的數據庫 FileOutputStream fos = null; try { fos = new FileOutputStream(dbPath); byte[] buffer = new byte[1024]; int count = 0; while ((count = is.read(buffer)) > 0) { fos.write(buffer, 0, count); } fos.flush(); fos.close(); is.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } Log.v(TAG, " " + (new File(dbPath).exists())); } }
3、完事了
4、也可以說,沒完事,因為加密的數據庫,我們還沒拿出來。
5、怎么拿出來呢,請點擊這里→《Android-從手機中拷貝文件到電腦-adb pull》http://www.cnblogs.com/iwanghang/p/8477420.html
6、真的完事了
7、解密的博客,請看下一篇
