利用SQLCipher加解密数据库(包括加解密已有的数据库)

1、介绍
    SQLCipher是一个在SQLite基础之上进行扩展的开源数据库,它主要是在SQLite的基础之上增加了数据加密功能,如果我们在项目中使用它来存储数据的话,就可以大大提高程序的安全性。SQLCipher支持很多种不同的平台,这里仅介绍Android中SQLCipher的用法。SQLCipher官网参见 https://www.zetetic.net/sqlcipher/
    
     网上的很多资料,大都说的是用sqlcipher加密,并通过密码来打开数据库及后续的增删改查操作等。但这些例子都是新建带密码的数据库,而非对已有的数据库进行加密和解密。对于已有的未加密的数据库,显然有极大的不便。另外一些资料,是通过sqlcipher的命令模式直接改密码,本人未做尝试,暂不做评论。基于此,才有了如下的项目。
     
2、利用AndroidStudio新建项目,并以gradle的方式将SQLCipher导入到我们的项目
在app级别的build.gradle中添加如下代码:
dependencies {
   compile 'net.zetetic:android-database-sqlcipher:3.5.4@aar'
}
然后,编译项目即可。

查询最新版本的SQLCipher,可参见如下网址 https://www.zetetic.net/sqlcipher/sqlcipher-for-android/

3、项目只有MainActivity.java和activity_main.xml两个文件:
  • 布局文件activity_main.xml代码如下:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        tools:context="com.wjk.sqlciphertest.MainActivity">
    
        <Button
            android:id="@+id/bt_encry"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="加密" />
    
        <Button
            android:id="@+id/bt_decry"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="解密" />
    </LinearLayout>
布局文件中包括加密和解密两个按钮。
  • 接下来在MainActivity.java中编写加密和解密方法。主要用到SQLiteDatabase.rawExecSQL()和sqlcipher_export()两个方法。先上代码:
    package com.***.sqlciphertest;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.Button;
    import net.sqlcipher.database.SQLiteDatabase;
    
    import java.io.File;
    
    public class MainActivity extends AppCompatActivity {
    
        private final String SDcardPath = "/mnt/sdcard/";
        private Button mEncryptButton;
        private Button mDecryptButton;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            SQLiteDatabase.loadLibs(this);//引用SQLiteDatabase的方法之前必须先添加这句代码
    
            mEncryptButton = (Button) findViewById(R.id.bt_encry);
            mDecryptButton = (Button) findViewById(R.id.bt_decry);
            mEncryptButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    encrypt("encryptedtest.db","test.db","1234");
                }
            });
    
            mDecryptButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    decrypt("encryptedtest.db","decryptedtest.db","1234");
                }
            });
        }
    
        /**
        * 加密数据库
        * @param encryptedName 加密后的数据库名称
        * @param decryptedName 要加密的数据库名称
        * @param key 密码
        */
        private void encrypt(String encryptedName,String decryptedName,String key) {
            try {
                File databaseFile = getDatabasePath(SDcardPath + decryptedName);
                SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFile, "", null);//打开要加密的数据库
    
                /*String passwordString = "1234"; //只能对已加密的数据库修改密码,且无法直接修改为“”或null的密码
                database.changePassword(passwordString.toCharArray());*/
    
                File encrypteddatabaseFile = getDatabasePath(SDcardPath + encryptedName);//新建加密后的数据库文件
                //deleteDatabase(SDcardPath + encryptedName);
    
                //连接到加密后的数据库,并设置密码
                database.rawExecSQL(String.format("ATTACH DATABASE '%s' as "+ encryptedName.split("\\.")[0] +" KEY '"+ key +"';", encrypteddatabaseFile.getAbsolutePath()));
                //输出要加密的数据库表和数据到加密后的数据库文件中
                database.rawExecSQL("SELECT sqlcipher_export('"+ encryptedName.split("\\.")[0] +"');");
                //断开同加密后的数据库的连接
                database.rawExecSQL("DETACH DATABASE "+ encryptedName.split("\\.")[0] +";");
    
                //打开加密后的数据库,测试数据库是否加密成功
                SQLiteDatabase encrypteddatabase = SQLiteDatabase.openOrCreateDatabase(encrypteddatabaseFile, key, null);
                //encrypteddatabase.setVersion(database.getVersion());
                encrypteddatabase.close();//关闭数据库
    
                database.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
        * 解密数据库
        * @param encryptedName 要解密的数据库名称
        * @param decryptedName 解密后的数据库名称
        * @param key 密码
        */
        private void decrypt(String encryptedName,String decryptedName,String key) {
            try {
                File databaseFile = getDatabasePath(SDcardPath + encryptedName);
                SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFile, key, null);
    
                File decrypteddatabaseFile = getDatabasePath(SDcardPath + decryptedName);
                //deleteDatabase(SDcardPath + decryptedName);
    
                //连接到解密后的数据库,并设置密码为空
                database.rawExecSQL(String.format("ATTACH DATABASE '%s' as "+ decryptedName.split("\\.")[0] +" KEY '';", decrypteddatabaseFile.getAbsolutePath()));
                database.rawExecSQL("SELECT sqlcipher_export('"+ decryptedName.split("\\.")[0] +"');");
                database.rawExecSQL("DETACH DATABASE "+ decryptedName.split("\\.")[0] +";");
    
                SQLiteDatabase decrypteddatabase = SQLiteDatabase.openOrCreateDatabase(decrypteddatabaseFile, "", null);
                //decrypteddatabase.setVersion(database.getVersion());
                decrypteddatabase.close();
    
                database.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
代码中已经做了详尽的注释,而且代码也很简单。主要是参考sqlcipher/sqlcipher-android-tests,网址见 https://github.com/sqlcipher/sqlcipher-android-tests

如果数据库是没有密码的,加密后,再打开数据库,则会提示file is encrypted or is not a database。再解密后,即可正常打开数据库。

不论是新建的数据库,还是已有的加密或没加密过的数据库,并且对更新数据库的数据都会带来极大的方便。

4、参考文献
sqlcipher/sqlcipher-android-tests: https://github.com/sqlcipher/sqlcipher-android-tests

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
SQLite数据库加密解密工具是指用于对SQLite数据库进行加密和解密操作的软件工具。 SQLite数据库是一种轻型的数据库管理系统,通常用于嵌入式设备或移动应用程序中。然而,SQLite数据库默认不支持加密功能,而在某些情况下,我们需要对数据库进行加密以保护数据安全性。 为了实现SQLite数据库的加密功能,可以借助一些第三方工具,如SQLCipherSQLCipher是一款专门为SQLite数据库提供加密功能的开源软件,它基于SQLite的代码库进行了修改和扩展,使得SQLite数据库可以支持AES加密算法和SHA-256哈希算法,从而提供了强大的安全性。 使用SQLCipher加密SQLite数据库的过程包括以下几个步骤: 1. 下载并安装SQLCipher库文件。 2. 在应用程序中将原始SQLite库替换为SQLCipher库。 3. 生成一个加密密码,并将其与SQLite数据库关联。 4. 在访问SQLite数据库之前,使用密码对数据库进行解密。 5. 对数据库进行操作后,将其重新加密。 通过使用SQLCipher,我们可以为SQLite数据库提供强大的加密功能,确保数据在存储和传输过程中的安全性。同时,解密工具也可以用来解密加密的SQLite数据库,以便进行数据的读取和操作。 总之,SQLite数据库加密解密工具是用于对SQLite数据库进行加密和解密操作的软件工具,可以通过使用第三方库如SQLCipher来实现数据库的加密保护,提供数据的安全性和保密性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值