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

转载请注明出处: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,是更侧重于文件大小,还是更侧重于程序安全,你应该根据具体的需求做出合适的判断。

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

源码下载,请点击这里

时间: 2024-11-03 22:06:59

Android数据库安全解决方案,使用SQLCipher进行加解密的相关文章

android中使用jni对字符串加解密实现分析

android中使用jni对字符串加解密实现分析 最近项目有个需求,就是要对用户的敏感信息进行加密处理,比如用户的账户密码,手机号等私密信息.在java中,就对字符串的加解密我们可以使用AES算法加密字符串,使用它的好处就不必多说了,但我们又知道android的源代码是可以被反编译的,所以使用纯Java方式的AES加密是不安全的,所以想到了使用android中的jni来对字符串加解密处理,它会产生一个.so文件,更重要的是它通过C/C++代码实现,所以安全行比较高,它可以被反编译成机器码,但几乎

【转】使用SQLCipher进行加解密

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

RSA在Android、vc、java下加解密实现互通。

最近公司项目需求要对上传/下载的数据进行AES+RSA的加解密需求,客户有vc的RSA加解密接口,而且说要与他们的系统兼容,也就是说vc下要用他们的模块实现加解密.期间过程有几个坑,原因都是自己的对这些加密的协议/准则/规范不熟,以此文记录备案. 坑1: 首先先是百度java的RSAUtils,网上很多现成的,例如这个:http://www.2cto.com/kf/201408/328112.html,公钥使用X509的解析类,私钥使用PKCS#8的解析类.编写测试程序一切正常... 然后就是调

[掌眼]iOS / Android / java / node.js 通用的 AES256 加解密算法

example.m NSString *text = @"text"; NSString *key32 = @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding]; NSString *encryptedData = [[data AES256EncryptWithKey:key32] base64EncodedStringWi

[转]PHP,Android,IOS通信之AES128加解密

转自:http://s00s10.blog.163.com/blog/static/43988552201411913011459/ android上使用: mcrypt = new MCrypt(); /* 加密*/ String encrypted = MCrypt.bytesToHex( mcrypt.encrypt("需加密的字符") ); /* 解密*/ String decrypted = new String( mcrypt.decrypt( encrypted ) );

多语言(Java&amp;C#&amp;Ruby&amp;C++&amp;Objective-C&amp;Android)互通的TripleDES加解密算法实现

直入主题:前段时间根据公司对开发API的安全性要求,采用了小数据加密验证的方式,根据需求采用了三重DES加密算法.在实施的过程中发现各个语言之间加密由于加密补位的方式有所不同,导致不同语言之间加密之后无法相互解析.在强大的会联网技术和公司其他同事的支持下,最终整合了集Java,C#,Ruby,C++,Objective-C,Android多语言的可以互通的TripleDES加密算法,虽然在AES加密推崇的今天DES有些乏力,但小可大胆贴上代码,希望能给大家提供一些思路. Java DES加密(J

微软企业级加解密解决方案MBAM架构

在之前的文章里,我给大家分享了<Bitlocker企业安全加密管理系列-1>和<Bitlocker企业安全加密管理系列-2>在这里我就不再给大家缀诉什么是MBAM了,在这里我主要给大家分享如何部署微软企业级加解密解决方案MBAM系列文章,在这里以MBAM2.5SP1为例,今天先给大家分享下架构: MBAM部署的模式有2种,一种是独立模式,一种是SCCM集成模式.2种架构图如下: 独立模式 SCCM集成模式 那么MBAM的逻辑架构是如下的: 如果您的企业需要部署MBAM的高可用架构,

Android jni aes加解密,实现文件的加解密,具体实现可以自行修改,上面的代码为简单介绍,下面的是JNI端实现文件加解密,可以修改为字符串加解密

#include "aes.h" #include "modes.h" #include "e_os2.h" #include "aes_locl.h" #include "opensslconf.h" AES_KEY aes; //aes cbc模式加解密用到的向量 unsigned char iv[AES_BLOCK_SIZE]; for (i = 0; i < AES_BLOCK_SIZE; i

DES跨(C# Android IOS)三个平台通用的加解密方法

#region   跨平台加解密(c# 安卓 IOS) //  public static string sKey = "12345678"; //  /// <summary> //  /// 解密 //  /// </summary> //  /// <param name="pToDecrypt">要解密的以Base64</param> //  /// <param name="sKey"