关闭

Android数据库安全解决方案,使用SQLCipher进行加解密

标签: Android数据库SQLiteSQLCipher加密
40204人阅读 评论(46) 收藏 举报
分类:

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11952409


我们都知道,Android系统内置了SQLite数据库,并且提供了一整套的API用于对数据库进行增删改查操作。数据库存储是我们经常会使用到的一种存储方式,相信大多数朋友对它的使用方法都已经比较熟悉了吧。在Android中,我们既可以使用原生的SQL语句来对数据进行操作,也可以使用Android API提供的CRUD方法来对数据库进行操作,两种方式各有特点,选择使用哪一种就全凭个人喜好了。


不过,使用SQLite来存储数据却存在着一个问题。因为大多数的Android手机都是Root过的,而Root过的手机都可以进入到/data/data/<package_name>/databases目录下面,在这里就可以查看到数据库中存储的所有数据。如果是一般的数据还好,但是当涉及到一些账号密码,或者聊天内容的时候,我们的程序就会面临严重的安全漏洞隐患。那么今天,就让我们一起研究一下如何借助SQLCipher来解决这个安全性问题。


SQLCipher是一个在SQLite基础之上进行扩展的开源数据库,它主要是在SQLite的基础之上增加了数据加密功能,如果我们在项目中使用它来存储数据的话,就可以大大提高程序的安全性。SQLCipher支持很多种不同的平台,这里我们要学习的自然是Android中SQLCipher的用法了。


下面我们就开始吧,首先要把Android项目所依赖的SQLCipher工具包下载下来,下载地址是:

https://s3.amazonaws.com/sqlcipher/SQLCipher+for+Android+v2.2.2.zip


接着解压这个工具包,会看到里面有assets和libs这两个目录,稍后需要将这两个目录中的内容添加到Android项目当中。那么现在我们就来新建一个Android项目,项目名就叫SQLCipherTest。


观察SQLCipherTest的项目结构,发现里面也分别有一个assets目录和一个libs目录,那么现在就可以把SQLCipher工具包中这两个目录里的内容复制过来。并不需要复制全部文件,选择必要的文件进行复制就可以了,完成以后项目结构图如下所示,图中显示的文件都是必要的。




到这里准备工作就全部完成了,接下来我们开始编写代码。首先创建一个MyDatabaseHelper继承自SQLiteOpenHelper,注意这里使用的并不是Android API中的SQLiteOpenHelper,而是net.sqlcipher.database包下的SQLiteOpenHelper,代码如下所示:

import android.content.Context;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteDatabase.CursorFactory;
import net.sqlcipher.database.SQLiteOpenHelper;

public class MyDatabaseHelper extends SQLiteOpenHelper {
	
	public static final String CREATE_TABLE = "create table Book(name text, pages integer)";

	public MyDatabaseHelper(Context context, String name, CursorFactory factory, int version) {
		super(context, name, factory, version);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_TABLE);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {

	}

}
除了引入的包不一样了,其它的用法和传统的SQLiteOpenHelper都是完全相同的。可以看到,我们在onCreate()方法中创建了一张Book表,Book表里有name和pages这两个列。


接着,打开或新建activity_main.xml作为程序的主布局文件,代码如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <Button 
        android:id="@+id/add_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="添加数据"
        />
    
    <Button 
        android:id="@+id/query_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查询数据"
        />

</LinearLayout>
这里只是简单地放置了两个按钮,分别用于添加和查询数据。接下来打开或新建MainActivity作为程序主Activity,代码如下所示:
public class MainActivity extends Activity {
	
	private SQLiteDatabase db;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		SQLiteDatabase.loadLibs(this);
		MyDatabaseHelper dbHelper = new MyDatabaseHelper(this, "demo.db", null, 1);
		db = dbHelper.getWritableDatabase("secret_key");
		Button addData = (Button) findViewById(R.id.add_data);
		Button queryData = (Button) findViewById(R.id.query_data);
		addData.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				ContentValues values = new ContentValues();
				values.put("name", "达芬奇密码");
				values.put("pages", 566);
				db.insert("Book", null, values);
			}
		});
		queryData.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Cursor cursor = db.query("Book", null, null, null, null, null, null);
				if (cursor != null) {
					while (cursor.moveToNext()) {
						String name = cursor.getString(cursor.getColumnIndex("name"));
						int pages = cursor.getInt(cursor.getColumnIndex("pages"));
						Log.d("TAG", "book name is " + name);
						Log.d("TAG", "book pages is " + pages);
					}
				}
				cursor.close();
			}
		});
	}

}

可以看到,在onCreate()方法中首先调用了SQLiteDatabase的loadLibs()静态方法将SQLCipher所依赖的so库加载进来,注意这里使用的是net.sqlcipher.database包下的SQLiteDatabase。然后我们创建了MyDatabaseHelper的实例,并调用getWritableDatabase()方法去获取SQLiteDatabase对象。这里在调用getWritableDatabase()方法的时候传入了一个字符串参数,它就是SQLCipher所依赖的key,在对数据库进行加解密的时候SQLCipher都将使用这里指定的key。


在添加数据按钮的点击事件里面,我们通过ContentValues构建了一条数据,然后调用SQLiteDatabase的insert()方法将这条数据插入到Book表中。


在查询数据按钮的点击事件里面,我们调用SQLiteDatabase的query()方法来查询Book表中的数据,查询到的结果会存放在Cursor对象中,注意这里使用的是net.sqlcipher包下的Cursor。然后对Cursor对象进行遍历,并将查询到的结果打印出来。


现在运行一下程序,先点击添加数据按钮,再点击查询数据按钮,刚刚添加的那条数据就应该在控制台里打印出来了。


有没有感觉到使用SQLCipher提供的API和使用Android原生的数据库API,操作起来几乎是一模一样的。没错,SQLCipher对Android SDK中所有与数据库相关的API都制作了一份镜像,使得开发者可以像操作普遍的数据库文件一样来操作SQLCipher,而所有的数据加解密操作,SQLCipher都在背后帮我们处理好了。


话说写到这里,我们都一直还没体验一下SQLCipher加密后的效果呢,现在就来看一看吧,首先通过命令行的方式来访问demo.db这个数据库文件:

adb shell
cd /data/data/com.example.sqlciphertest/databases
sqlite3 -line demo.db
.table

尝试查看demo.db中的所有表,结果返回如下图所示:


  

从图中可以看出,当执行.table命令的时候被拒绝了,原因是数据库文件已加密。


除了使用命令行的方式,我们还可以尝试使用Root Explorer来打开数据库文件,结果如下图所示:



意料之中,果然打开失败了。这就足以说明,目前数据库中的数据是非常安全的,只有在应用程序里通过SQLCipher提供的API才可以访问到数据库里的数据,使用其它的方式都无法获取其数据。


需要提醒的一点是,项目中引入了SQLCipher之后,会让你的程序体积骤然增加,打成APK后大概会变大好几M,是更侧重于文件大小,还是更侧重于程序安全,你应该根据具体的需求做出合适的判断。


好了,今天的讲解到此结束,有疑问的朋友请在下面留言。


源码下载,请点击这里


关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

微信扫一扫下方二维码即可关注:

        

48
2
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

Android数据库加密

Android数据库加密 一、简介 SQLite是一个轻量的、跨平台的、开源的数据库引擎,它的读写效率、资源消耗总量、延迟时间和整体简单性上具有的优越性,使其成为移动平台数据库的最佳解决方案(如A...
  • qq_19711823
  • qq_19711823
  • 2016-03-24 19:43
  • 2278

Android 数据库加密

一 简介             SQLite是一个轻量的、跨平台的、开源的数据库引擎,它的读写效率、资源消耗总量、延迟时间和整体简单性上具有的优越性,使其成为移动平台数据库的最佳解决方案(如An...
  • FX_SKY
  • FX_SKY
  • 2014-11-16 22:29
  • 4921

Android使用SQLCipher对数据库文件加密

查了好多资料,大多数都是抄来抄去,还有很多文章时间都是几年前的了。根据SQLCipher在github上的公开的资料,做一个教程。SQLCipher是对数据库文件加密,不是对数据库内容加密。这一点要分...
  • wshngyf
  • wshngyf
  • 2016-04-10 14:11
  • 5052

Ndk把密码打包在so动态库中调用libsqlcipher_android.so

在Android上保护数据,对sqlite 数据库加密(SQLCipher) Android.mk 代码 LOCAL_PATH := $(call my-dir) include ...
  • lixiaozhong
  • lixiaozhong
  • 2016-11-25 08:04
  • 850

SQLCipher windows lib

  • 2015-08-13 19:18
  • 2.89MB
  • 下载

sqlcipher的移植

一、下载代码:http://git.oschina.net/fulinux/sqlcipher.git或者https://github.com/sqlcipher/sqlcipher.git二、编译:...
  • sonbai
  • sonbai
  • 2014-07-28 11:30
  • 3199

Greendao打印Didn't find class "net.sqlcipher.database.SQLiteOpenHelper”解决办法

最近在使用greenDao数据库的时候,发现每次调试都会打印很多 java.lang.ClassNotFoundException: Didn’t find class “net.sqlcipher...
  • yuzhiqiang_1993
  • yuzhiqiang_1993
  • 2017-09-07 15:56
  • 1417

Android studio中使用sqlcipher安卓7.0中.so文件加载失败问题。

最近做项目的时候,甲方使用绿盟对APK进行了扫描。发现数据库存在安全漏洞,网上查阅众多资料,最后选用了sqlcipher来进行数据库加密。 关于sqlcipher的使用具体请参考[http:...
  • qklnmc
  • qklnmc
  • 2017-09-13 16:21
  • 371

sqlcipher 加密数据库问题3

1、加密数据库sqlcipher 2.2 (大约),yunxing
  • zhanghw0917
  • zhanghw0917
  • 2014-09-04 20:12
  • 10996

Android Sqlcipher解密数据库思路

在上一讲中 Android 使用Sqlcipher给Sqlite加密,我们学习了如何给数据库加密,但有时候我们想看加密数据库中的内容是否有错误,该如何解密呢。Sqlcipher的jar包没有这个方法,...
  • Gary__123456
  • Gary__123456
  • 2017-07-16 22:03
  • 578
    个人资料
    • 访问:7898618次
    • 积分:41920
    • 等级:
    • 排名:第98名
    • 原创:103篇
    • 转载:0篇
    • 译文:6篇
    • 评论:14259条
    我的新书
    微信公众号推荐

    关注我的技术公众号,每天都有优质技术文章推送。

    关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫上方二维码即可关注

    共同进步
    感兴趣的朋友可以加入我的QQ群,一起讨论学习,共同进步。
    群号:153325493
    人数有限,请不要重复加群 (即满)
    博客专栏
    最新评论
    统计