Android-使用sqlcipher加密解密本地數據庫-加密


如果你的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 pullhttp://www.cnblogs.com/iwanghang/p/8477420.html

6、真的完事了

7、解密的博客,請看下一篇


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM