Preface:
Recently, we have studied data sharing between Android Sqlite database and ContentProvider programs. We clearly know that the default storage location of the Sqlite database is in the data/data/pakage/database directory. There is no security for mobile phones that have already ROOT. Once it is used, it will lead to database data leakage. So how can we avoid this? We try to encrypt the database.
Choose the encryption scheme:
1.) The first solution
We can just encrypt the database name, table name, and column name of the data, and encrypt the stored data, such as AES encryption (Android data encryption Aes encryption), and then decrypt the data during query. This method cannot be said to be bad, but when you use it, you can imagine the degree of trouble it brings.
2.) The second solution
Using a third-party encryption open source library, we searched for many Android database encryption solutions, and finally selected the open source framework of SQLCipher. Let’s take a look at how to use SqlCipher.
Introduction to SQLCipher:
SQLCipher is an open source database that extends on the basis of SQLite. SQLCipher has a small footprint and performance, so it is very suitable for database protection for embedded applications and is very suitable for mobile development.
Advantages:
- High encryption performance and small overhead, only 5-15% of the overhead is used for encryption
- Completely achieve 100% encryption of the database
- Adopt good encryption method (CBC encryption mode)
- Easy to use and achieve application-level encryption
- Using the algorithm provided by the OpenSSL encryption library
How to use SQLCipher:
1.) Add the following code to the article, the latest version 3.4.0 is currently used
dependencies { compile ':android-database-sqlcipher:3.4.0' }
2.) Create a SQLiteOpenHelper Note the following class references to all Sqlite-related classes
import ; import ; import ; import ; import ; public class DBCipherHelper extends SQLiteOpenHelper { private static final String TAG = "DatabaseHelper"; private static final String DB_NAME = "test_cipher_db";//Database name public static final String DB_PWD="whoislcj";//Database Password public static String TABLE_NAME = "person";// Table name public static String FIELD_ID = "id";// Column name public static String FIELD_NAME= "name";// Column name private static final int DB_VERSION = 1; // Database version public DBCipherHelper(Context context, String name, factory, int version) { super(context, name, factory, version); //Not negligible to load the so library (context); } public DBCipherHelper(Context context) { this(context, DB_NAME, null, DB_VERSION); } /** * Create a database * @param db */ @Override public void onCreate(SQLiteDatabase db) { //Create a table createTable(db); } private void createTable(SQLiteDatabase db){ String sql = "CREATE TABLE " + TABLE_NAME + "(" + FIELD_ID + " integer primary key autoincrement , " + FIELD_NAME + " text not null);"; try { (sql); } catch (SQLException e) { (TAG, "onCreate " + TABLE_NAME + "Error" + ()); return; } } /** * Database upgrade * @param db * @param oldVersion * @param newVersion */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
Note: (context); Don't forget to call this
3.) Create a DBCipherManager database management
The specific implementation of traditional SQLiteOpenHelper is exactly the same, and the different places are where the database handle is obtained
Traditional way:
//Get the writable database SQLiteDatabase db = (); //Get readable database SQLiteDatabase db = ();
The current way: you need to pass in a password, which is the secret key used for encryption
//Get the write database SQLiteDatabase db = (DBCipherHelper.DB_PWD); //Get readable database SQLiteDatabase db = (DBCipherHelper.DB_PWD);
Next is the specific implementation:
import ; import ; import ; import ; import ; import ; /** * Database Manager - Provide database encapsulation * */ public class DBCipherManager { private static final String TAG = "DatabaseManager"; // Static reference private volatile static DBCipherManager mInstance; // DatabaseHelper private DBCipherHelper dbHelper; private DBCipherManager(Context context) { dbHelper = new DBCipherHelper(()); } /** * Get singleton reference * * @param context * @return */ public static DBCipherManager getInstance(Context context) { DBCipherManager inst = mInstance; if (inst == null) { synchronized () { inst = mInstance; if (inst == null) { inst = new DBCipherManager(context); mInstance = inst; } } } return inst; } /** * Insert data */ public void insertData(String name) { //Get the write database SQLiteDatabase db = (DBCipherHelper.DB_PWD); //Generate key values to be modified or inserted ContentValues cv = new ContentValues(); (DBCipherHelper.FIELD_NAME, name); // insert operation (DBCipherHelper.TABLE_NAME, null, cv); //Close the database (); } /** * Transaction batch insertion is not enabled * @param testCount */ public void insertDatasByNomarl(int testCount){ //Get the write database SQLiteDatabase db = (DBCipherHelper.DB_PWD); for(int i =0;i<testCount;i++ ){ //Generate key values to be modified or inserted ContentValues cv = new ContentValues(); (DBCipherHelper.FIELD_NAME, (i)); // insert operation (DBCipherHelper.TABLE_NAME, null, cv); (TAG, "insertDatasByNomarl"); } //Close the database (); } /** * Test enable transaction batch insertion * @param testCount */ public void insertDatasByTransaction(int testCount){ //Get the write database SQLiteDatabase db = (DBCipherHelper.DB_PWD); (); // Set up the start transaction manually try{ //Batch processing operation for(int i =0;i<testCount;i++ ){ //Generate key values to be modified or inserted ContentValues cv = new ContentValues(); (DBCipherHelper.FIELD_NAME, (i)); // insert operation (DBCipherHelper.TABLE_NAME, null, cv); (TAG, "insertDatasByTransaction"); } (); //The transaction processing is successfully set, if it is not set, it will automatically roll back and not commit }catch(Exception e){ }finally{ (); // Processing is completed //Close the database (); } } /** * Delete data */ public void deleteData(String name) { //Generate conditional statement StringBuffer whereBuffer = new StringBuffer(); (DBCipherHelper.FIELD_NAME).append(" = ").append("'").append(name).append("'"); //Get the write database SQLiteDatabase db = (DBCipherHelper.DB_PWD); // delete operation (DBCipherHelper.TABLE_NAME, (), null); //Close the database (); } /** * Delete all data */ public void deleteDatas() { String sql="delete from "+ DBCipherHelper.TABLE_NAME; execSQL(sql); } /** * Update data */ public void updateData(String name) { //Generate conditional statement StringBuffer whereBuffer = new StringBuffer(); (DBCipherHelper.FIELD_NAME).append(" = ").append("'").append(name).append("'"); //Generate key values to be modified or inserted ContentValues cv = new ContentValues(); (DBCipherHelper.FIELD_NAME, name+name); //Get the write database SQLiteDatabase db = (DBCipherHelper.DB_PWD); // update operation (DBCipherHelper.TABLE_NAME, cv, (), null); //Close the database (); } /** * Specify the conditions to query data */ public void queryDatas(String name){ //Generate conditional statement StringBuffer whereBuffer = new StringBuffer(); (DBCipherHelper.FIELD_NAME).append(" = ").append("'").append(name).append("'"); //Specify which columns of data to be queried String[] columns = {DBCipherHelper.FIELD_NAME}; //Get readable database SQLiteDatabase db = (DBCipherHelper.DB_PWD); //Query the database Cursor cursor = null; try { cursor = (DBCipherHelper.TABLE_NAME, columns, (), null, null, null, null); while (()) { int count = (); String columName = (0); String tname = (0); (TAG, "count = " + count + " columName = " + columName + " name = " +tname); } if (cursor != null) { (); } } catch (SQLException e) { (TAG, "queryDatas" + ()); } //Close the database (); } /** * Query all data */ public void queryDatas(){ //Specify which columns of data to be queried String[] columns = {DBCipherHelper.FIELD_NAME}; //Get readable database SQLiteDatabase db = (DBCipherHelper.DB_PWD); //Query the database Cursor cursor = null; try { cursor = (DBCipherHelper.TABLE_NAME, columns, null, null, null, null, null);//Get data cursor while (()) { int count = (); String columeName = (0);//Get the table structure column name String name = (0);//Get table structure column data (TAG, "count = " + count + " columName = " + columeName + " name = " +name); } //Close cursor to prevent memory leak if (cursor != null) { (); } } catch (SQLException e) { (TAG, "queryDatas" + ()); } //Close the database (); } /** * Execute SQL statements */ private void execSQL(String sql){ //Get the write database SQLiteDatabase db = (DBCipherHelper.DB_PWD); //Execute the SQL statement directly (sql);//or //Close the database (); } }
4.) How to call it
//Clear data ().deleteDatas(); //Insert data for (int i = 0; i < 10; i++) { ().insertData((i)); } //Delete data ().deleteData((5)); //Update data ().updateData((3)); //Query data ().queryDatas();
5.) Transaction support is the same as traditional
//Get the write database SQLiteDatabase db = (); (); // Set up the start transaction manually try{ // Handle batch operations here for(int i =0;i<testCount;i++ ){ //Generate key values to be modified or inserted ContentValues cv = new ContentValues(); (DBHelper.FIELD_NAME, (i)); // insert operation (DBHelper.TABLE_NAME, null, cv); } (); //The transaction processing is successfully set, if it is not set, it will automatically roll back and not commit }catch(Exception e){ }finally{ (); // Processing is completed //Close the database (); }
Summarize:
The SQLCipher usage summary ends here.
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.