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"><Buttonandroid:id="@+id/bt_encry"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="加密" /><Buttonandroid: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;@Overrideprotected 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() {@Overridepublic void onClick(View v) {encrypt("encryptedtest.db","test.db","1234");}});mDecryptButton.setOnClickListener(new View.OnClickListener() {@Overridepublic 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官网: https://www.zetetic.net/sqlcipher/sqlcipher-for-android/
sqlcipher/sqlcipher-android-tests: https://github.com/sqlcipher/sqlcipher-android-tests。
源码下载

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

  1. 无法打开数据库‘Data’.恢复操作已将数据库标记为SUSPECT。

    假如你是通过两个文件Data.mdf和Datalog.ldf来恢复数据库时,可能会遇到以下问题 一般恢复数据时通过附加选择文件Data.mdf进行操作就ok了,问题是可能Datalog.ldf有问题, ...

  2. 易语言mysql怎么写字段值_易语言数据库怎么加字段 数据库添加字段说明

    易语言将access数据库作为数据源怎么添加记录到access? .版本 2 .支持库 eDB 数据库连接1.连接Access (取运行目录 () + "数据库名称", " ...

  3. Druid连接池自定义数据库密码加解密的实现

    Druid的功能 1.替换DBCP和C3P0.Druid提供了一个高效.功能强大.可扩展性好的数据库连接池. 2.可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能 ...

  4. Android数据库加解密逆向分析(三)——微信数据库密码破解

    接着上一篇文章,在上一篇文章中我们通过对Line数据库加密的逆向分析,了解到了对要写入到数据库中的数据加密,读取时再将读取出的数据解密这种Android上的数据库加密方式.这篇文章来通过介绍对微信数据 ...

  5. android xml加密解密,华为配置加解密工具

    华为配置加解密工具是一款实用的加密解密软件,支持XML加解密,支持CFG加解密,支持密文解密等等,加密强度高非常安全,解密快不影响源文件,可以有效保障隐私重要文件的安全,有需要的朋友欢迎使用. 常见问 ...

  6. Android逆向:某薇直播通过ClassLoader加载的jar包解密

    声明:案例分析仅供学习交流使用,勿用于任何非法用途.如学习者进一步逆向并对版权方造成损失,请自行承担法律后果,本人概不负责. 简介 热修复和插件化是目前比较热门的技术,它们都是通过ClassLoade ...

  7. Python实现AES中ECB模式pkcs5padding填充加密/解密(需要加密文档中可以有中文)

    Python实现AES中ECB模式pkcs5padding填充加密/解密(需要加密文档中可以有中文) 一.本文主要解决的问题 二.完整版代码 结果: 三.遇到的问题 1.填充格式错误 2.传入类型错误 ...

  8. aes js 加盐值 解密_crypto-js aes加密解密

    安装 npm install crypto-js --save unit.js import CryptoJS from "crypto-js"; //秘钥 const CRYPT ...

  9. Spring-Web - 数据库 字段加密 解密

      在工作中,为了保证数据安全,需要对数据库字段进行加解密,之前工作中就遇到了这种情况,因为线上数据库有很多的人都有权限,运维,账务,运营(通过后台系统查看),出口太多了,但有用户向我们平台举报,说有 ...

最新文章

  1. Genymotion-启动报错Unable to load VirtualBox engine....
  2. APP启动速度是门面,如何做到极致优化?
  3. 【机器视觉】 endwhile算子
  4. 【Centos7】安装memcached
  5. android点击切换,android 导航栏中的按钮的点击切换
  6. 日积月累系列之分页控件(js源码)
  7. delphi 获取数组长度_C++可变长的数组,老司机手把手教你实现!
  8. maven使用国内源和使用代理
  9. distpicker初始化以及设定指定值
  10. 程序设计基础II学习笔记
  11. 社交类APP原型模板分享——Tinder
  12. PCtolcd2002提字库的字节计算方法
  13. C++编写红警3 1.12版本修改器
  14. 短期工作经历到底要不要写到简历上?
  15. Self-Supervised Vision Transformers with DINO-代码研读
  16. linux编辑原列表后怎么保存,linux下vi命令 修改文件及保存的使用方法(转)
  17. VIVADO 自定义封装ip核(超详细)
  18. openstack平台上创建云主机
  19. (三十七:2021.01.13)Pre-MICCAI 2019学习(二)《前列腺近距离放射治疗中,检测粒子在CT中的3D位置和方向》
  20. [渗透测试学习靶机02] vulnhub靶场 Empire: Breakout

热门文章

  1. secureCRT中配色方案推荐color scheme (solarized)
  2. PHPCMS v9 手机端栏目绑定模板
  3. android 开机动画竖屏,Android 5.0 开机横屏修改方法
  4. Windows各版本GVLK密钥表
  5. 解决网上下载PPT打不开的问题(0xc0000022)
  6. PHP 实现全站静态化 首页静态化 列表页静态化 内容静态化 .
  7. 通过Flash上传文件提示出错:onHTTPError
  8. 约瑟环的python实现(举例说明)
  9. 德纳社区:为什么Dmail这么热?可以给参与者带来什么财富?给大家做个梳理讲解
  10. arm linux设置ip地址命令,ARM Linux系统修改动态IP为静态IP地址