Android database encryption and android Database Encryption
1 Introduction
SQLite is a lightweight, cross-platform, open-source database engine. It has advantages in terms of read/write efficiency, total resource consumption, latency, and overall simplicity, make it the best solution for mobile platform databases (such as Android and iOS ). The Android system has a built-in SQLite database and provides a complete set of APIS for adding, deleting, modifying, and querying databases.
However, SQLite on the Android platform has a fatal flaw: encryption is not supported. This allows anyone to view the data stored in SQLite in any text editor. If it is normal data, but when it involves some account passwords or chat content, our applications will face severe security vulnerabilities.
Solution 2
1. SQLite Encryption Method
There are two ways to encrypt databases:
Encrypt the content before writing it to the database.
This method is easy to use. In the warehouse receiving/warehouse picking process, you only need to perform the corresponding encryption and decryption operations on the fields. To a certain extent, the problem of naked data exposure is solved.
However, this method is not completely encrypted because the table structure and other information of the database can still be viewed. In addition, after the content written to the database is encrypted, searching is also a problem.
Encrypt database files
Encrypting the entire database file can solve the information security problem of the database. Currently, the existing SQLite encryption is basically implemented in this way.
2. SQLite encryption tool
Today we are talking about SQLCipher, an open-source SQLite encryption tool. SQLCipher is fully open-source and its code is hosted on github.
SQLCipher uses 256-bit AES encryption. Because it is based on the free version of SQLite, the main encryption interface is the same as SQLite, but some of its own interfaces are also added. In fact, SQLite has a decryption interface, but the free version is not implemented.
SQLCipher is divided into Community Edition and Commercial Edition. The former is free of charge. For more information about SQLCipher Features, see here.
Cross-platform support is officially described as follows:
SQLCipher has broad platform support for with C/C ++, Obj-C, QT, Win32 /. NET, Java, Python, Ruby, Linux, Mac OS X, iPhone/iOS, Android, Xamarin. iOS, and Xamarin. android (such as iOS and Android ).
Both Android and iOS platforms are supported.
3. SQLCipher Integration
SQLCipher provides detailed integration instructions. For more information, see here.
The following is a simple example to demonstrate how to quickly integrate SQLCipher into our project.
3.1 download the official Binary Package
: Https://s3.amazonaws.com/sqlcipher/3.2.0/sqlcipher-for-android-community-v3.2.0.zip
3.2 import dependency files
Decompress the downloaded compressed package as follows:
Copy all the files in the libs and assets directories to our current project. After the copy is completed, it is as follows:
3.3 database operations
First, the custom MySQLiteOpenHelper inherits from the net. sqlcipher. database. SQLiteOpenHelper class, instead of the android. database. sqlite. SQLiteOpenHelper class. Remember! The sample code is as follows:
package com.ricky.android.sqlitecipher.db;import com.ricky.android.sqlitecipher.util.Logger;import android.content.Context;import net.sqlcipher.database.SQLiteDatabase;import net.sqlcipher.database.SQLiteDatabase.CursorFactory;import net.sqlcipher.database.SQLiteOpenHelper;public class MySQLiteOpenHelper extends SQLiteOpenHelper {private static final String DB_NAME = "test.db";private static final int DB_VERSION = 3;public MySQLiteOpenHelper(Context context){super(context, DB_NAME, null, DB_VERSION);}public MySQLiteOpenHelper(Context context, String name,CursorFactory factory, int version) {super(context, name, factory, version);}@Overridepublic void onCreate(SQLiteDatabase db) {Logger.e("MySQLiteOpenHelper", "onCreate db name="+DB_NAME+" version="+DB_VERSION);db.execSQL("CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT, name text, age integer)");}@Overridepublic void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {// TODO Auto-generated method stub}}
Then we use SQLiteDatabase in our DAO class to operate the database. Note: Here is net. sqlcipher. database. SQLiteDatabase, instead of android. database. sqlite. SQLiteDatabase. Do not introduce the wrong package!
package com.ricky.android.sqlitecipher.dao;import java.util.ArrayList;import java.util.List;import net.sqlcipher.Cursor;import net.sqlcipher.database.SQLiteDatabase;import net.sqlcipher.database.SQLiteOpenHelper;import android.content.ContentValues;import android.content.Context;import com.ricky.android.sqlitecipher.db.SQLiteHelperFactory;import com.ricky.android.sqlitecipher.model.Student;public class StudentDAOImpl implements StudentDAO { private SQLiteOpenHelper sqLiteOpenHelper; private String password = "ricky"; public StudentDAOImpl(Context context){sqLiteOpenHelper = SQLiteHelperFactory.create(context);}@Overridepublic long insert(Student stu) {SQLiteDatabase db = null;try{db = sqLiteOpenHelper.getWritableDatabase(password);ContentValues values = new ContentValues(); values.put("name", "Ricky"); values.put("age", 24); return db.insert("student", null, values);}finally{if(db!=null)db.close();}}@Overridepublic List<Student> query() {SQLiteDatabase db = null;Cursor cursor = null;try{db = sqLiteOpenHelper.getWritableDatabase(password); cursor = db.query("student", new String[]{"id","name","age"}, null, null, null, null, null);List<Student> list = new ArrayList<>();while(cursor!=null && cursor.moveToNext()){Student stu = new Student();stu.setId(cursor.getInt(0));stu.setName(cursor.getString(1));stu.setAge(cursor.getInt(2));list.add(stu);}return list;}finally{if(cursor!=null){cursor.close();}if(db!=null)db.close();}}}
Here, the crud of data is basically implemented, but you need to pay attention to the following points:
You must call SQLiteDatabase. loadLibs (context) first, and then perform database-related operations.
To facilitate management, I independently wrote a SQLiteHelperFactory class to create SQLiteOpenHelper. After creating the MySQLiteOpenHelper object, I will call SQLiteDatabase. loadLibs (context); the Code is as follows:
Package com. ricky. android. sqlitecipher. db; import com. ricky. android. sqlitecipher. util. logger; import android. content. context; import net. sqlcipher. database. SQLiteDatabase; import net. sqlcipher. database. SQLiteOpenHelper;/*** SQLiteOpenHelper factory * @ author Ricky **/public class SQLiteHelperFactory {private static final String TAG = SQLiteHelperFactory. class. getSimpleName (); private static SQLiteOpenHelper sqLiteOpenHelper; private SQLiteHelperFactory () {} public static synchronized create (Context context) {if (SQLiteOpenHelper = null) {synchronized (SQLiteHelperFactory. class) {if (sqLiteOpenHelper = null) {Logger. e (TAG, "init SQLiteOpenHelper"); sqLiteOpenHelper = new MySQLiteOpenHelper (context. getApplicationContext (); Logger. e (TAG, "SQLiteDatabase loadLibs"); // This method must be called first. loadLibs (context) ;}}return sqLiteOpenHelper ;}}
MainActivity class
package com.ricky.android.sqlitecipher;import java.util.List;import com.ricky.android.sqlitecipher.dao.StudentDAO;import com.ricky.android.sqlitecipher.dao.StudentDAOImpl;import com.ricky.android.sqlitecipher.model.Student;import com.ricky.android.sqlitecipher.util.Logger;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class MainActivity extends Activity implements OnClickListener {private static final String TAG = MainActivity.class.getSimpleName();private Button bt_insert;private Button bt_query;private StudentDAO studentDAO;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById();setListener();processLogic();}private void findViewById() {bt_insert = (Button) findViewById(R.id.bt_insert);bt_query = (Button) findViewById(R.id.bt_query);}private void setListener() {bt_insert.setOnClickListener(this);bt_query.setOnClickListener(this);}private void processLogic() {studentDAO = new StudentDAOImpl(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.bt_insert:Student stu = new Student();stu.setName("Mike");stu.setAge(24);long id = studentDAO.insert(stu);Logger.i(TAG, "insert id="+id);break;case R.id.bt_query:List<Student> list = studentDAO.query();if(list!=null){Logger.i(TAG, "student list size="+list.size());}else{Logger.i(TAG, "student list is empty");}break;default:break;}}}
OK. The integration of SQLCipher is complete here, And the Demo source code is attached (see the end of the article). If you have any questions, please leave a message!
Demo: http://download.csdn.net/detail/fx_sky/8165223