Android 数据库加密 SQLCipher使用方法

Android 数据库加密 SQLCipher使用方法

最近在做数据库加密,遇到了些问题,特此记录

greendao 支持数据库加密
网址http://greenrobot.org/greendao/documentation/database-encryption/

SQLCipher 网址:https://www.zetetic.net/sqlcipher/

SQLCipher 如何依赖在Android
网址:https://www.zetetic.net/sqlcipher/sqlcipher-for-android/

AS依赖 compile ‘net.zetetic:android-database-sqlcipher:3.5.9@aar’

每次在操作数据库前,初始化SQLCipher 所以我放在了Application下

SQLiteDatabase.loadLibs(APPApplication.this);

  • 在操作数据库时与SQLiteDatabase 基本一样,唯一的区别就是打开数据库,需要密码
  • 首先打开一个加密的数据库

sqlcipher 打开加密数据库


net.sqlcipher.database.SQLiteDatabase  sqLiteDatabase = net.sqlcipher.database.SQLiteDatabase.openDatabase(file.getAbsolutePath(), password, null,
                        SQLiteDatabase.OPEN_READWRITE
                                | SQLiteDatabase.CREATE_IF_NECESSARY
                                | SQLiteDatabase.NO_LOCALIZED_COLLATORS, new SQLiteDatabaseHook() {
                            @Override
                            public void preKey(net.sqlcipher.database.SQLiteDatabase sqLiteDatabase) {

                            }

                            @Override
                            public void postKey(net.sqlcipher.database.SQLiteDatabase sqLiteDatabase) {
                               //操作数据与 Android SQLiteDatabase 用法一致
                            }
                        });


//greendao 操作数据库时 用这个方法 打开加密的库
openHelper.getEncryptedWritableDb(Contents.DB_KEY);
openHelper.getEncryptedReadableDb(Contents.DB_KEY);

greendao 中结合 sqlcipher 用法:


    /**
     * 获取可读数据库
     */
    private Database getReadableDatabase() {
        if (Contents.DB_RELEASE) {
            DBencrypt.getInstences().encrypt(UIUtil.getContext(), Contents.DB_KEY);
            return openHelper.getEncryptedReadableDb(Contents.DB_KEY);
        } else {
            return openHelper.getReadableDb();
        }
    }

    /**
     * 获取可写数据库
     */
    private Database getWritableDatabase() {
        if (Contents.DB_RELEASE) {
            DBencrypt.getInstences().encrypt(UIUtil.getContext(), Contents.DB_KEY);
            return openHelper.getEncryptedWritableDb(Contents.DB_KEY);
        } else {
            return openHelper.getReadableDb();
        }
    }

做完后遇到一个尴尬的问题,第一次进去时确实能显示,没毛病,当把进程杀死后在进去,都报错。。。

net.sqlcipher.database.SQLiteException: file is not a database: , while compiling: select count(*) from sqlite_master;

查询多次后发现 是加密 解密时出问题,当数据库原来未加密时用此方法打开,会报错。所以在查询数据之前,先把未加密的数据库加密,再去查询

代码附上:

    /**
     * 加密数据库
     * Created by Han on 2018/4/10
     * Email:yin13753884368@163.com
     * CSDN:http://blog.csdn.net/yin13753884368/article
     * Github:https://github.com/yin13753884368
     */

    public class DBencrypt {
        public static DBencrypt dBencrypt;
        private Boolean isOpen = true;

        public static DBencrypt getInstences() {
            if (dBencrypt == null) {
                synchronized (DBencrypt.class) {
                    if (dBencrypt == null) {
                        dBencrypt = new DBencrypt();
                    }
                }
            }
            return dBencrypt;
        }

        /**
         * 如果有旧表 先加密数据库
         *
         * @param context
         * @param passphrase
         */
        public void encrypt(Context context, String passphrase) {
            File file = new File("/data/data/" + context.getPackageName() + "/databases/db_name");
            if (file.exists()) {
                if (isOpen) {
                    try {
                        File newFile = File.createTempFile("sqlcipherutils", "tmp", context.getCacheDir());

                        net.sqlcipher.database.SQLiteDatabase db = net.sqlcipher.database.SQLiteDatabase.openDatabase(
                                file.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 = net.sqlcipher.database.SQLiteDatabase.openDatabase(newFile.getAbsolutePath(),
                                passphrase, null,
                                SQLiteDatabase.OPEN_READWRITE);

                        db.setVersion(version);
                        db.close();
                        file.delete();
                        newFile.renameTo(file);
                        isOpen = false;
                    } catch (Exception e) {
                        isOpen = false;
                    }
                }
            }
        }
    }

官网文档地址:https://www.zetetic.net/sqlcipher/sqlcipher-api/#attach

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值