In this lab, you will learn how to do encryption by using Android embedded SQLite with Cipher.
Learn how to store data in the Android SQLite
Learn how to use Cipher to encrypt and decrypt data in the Android SQLite
Implement an Android program that encrypts and decrypts data using Cipher in the SQLite database.
"You should never attempt to penetrate a system or attempt to adversely affect its operating system. Such actions are a violation of SPSU's policy and, in some cases, a violation of state or federal law. Likewise, you should refrain from writing computer viruses, worms, self-reproducing code, or other kinds of damaging software for this course unless you have explicit, written approval for the specific type of software that you wish to create. These kinds of programs are notoriously difficult to control and their release can result in substantial civil and criminal penalties. Please read and review the ACM code of ethics and professional conduct policy."
Cipher is a quite simple API in Android. Its main function is to encrypt and decrypt data in the Android SQLite database. Users can just create a password and it can be delivered to methods for encryption and decryption.
Start a new project in Android Studio:
First, create a new Android Studio project and choose "Empty Activity". Click "Next"
Name it “MyApplication” with the company domain of "com.example.cipher.myapplication" and click on Next
Right Click on "com.example.cipher.myapplication--> New-->Java Class"
Name the class as "EventDataSQLHelper"
Create two folders on "AndroidStudioProject--> MyApplication --> app-->src-->main" and name "assets" & "jniLibs". You also need to create the folders and files marked as red
Copy and paste all the following code in the specified file
//Copy and paste the code in MainActivity.java into MainActivity. NOTE: the package might be different.
//MainActivity.java
package com.example.cipher.myapplication;
import android.content.ContentValues;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import net.sqlcipher.Cursor;
import net.sqlcipher.database.SQLiteDatabase;
public class MainActivity extends AppCompatActivity {
EventDataSQLHelper eventsData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SQLiteDatabase.loadLibs(this);
String password = "pass";
eventsData = new EventDataSQLHelper(this);
SQLiteDatabase database = eventsData.getWritableDatabase("pass");
addEvent("Succeed", database);
database.close();
database = eventsData.getReadableDatabase(password);
Cursor cursor = database.query(EventDataSQLHelper.TABLE, null, null, null, null, null, null);
cursor.moveToFirst();
//you could also do these things
Long first = cursor.getLong(0);
Long time = cursor.getLong(1);
String title = cursor.getString(2);
//String convert = first.toString();
Toast.makeText(getApplicationContext(), title, Toast.LENGTH_LONG).show();
cursor.close();
database.close();
}
private void addEvent(String title, SQLiteDatabase db) {
ContentValues values = new ContentValues();
values.put(EventDataSQLHelper.TIME, "demo");
values.put(EventDataSQLHelper.TITLE, title);
db.insert(EventDataSQLHelper.TABLE, null, values);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
//Copy the following code into the newly created “EventDataSQLHelper.java”.
//EventDataSQLHelper.java
package com.example.cipher.myapplication;
import android.content.Context;
import android.provider.BaseColumns;
import android.util.Log;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteOpenHelper;
/**
* Created by Monkey on 11/19/2015.
*/
public class EventDataSQLHelper extends SQLiteOpenHelper{
private static final String DATABASE_NAME = "events.db";
private static final int DATABASE_VERSION = 1;
// Table name
public static final String TABLE = "events";
// Columns
public static final String TIME = "time";
public static final String TITLE = "title";
public EventDataSQLHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table " + TABLE + "( " + BaseColumns._ID
+ " integer primary key autoincrement, " + TIME + " integer, "
+ TITLE + " text not null);";
//Log.d("EventsData", "onCreate: " + sql);
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion >= newVersion)
return;
String sql = null;
if (oldVersion == 1)
sql = "alter table " + TABLE + " add note text;";
if (oldVersion == 2)
sql = "";
Log.d("EventsData", "onUpgrade : " + sql);
if (sql != null)
db.execSQL(sql);
}
}
//Copy and paste the code in build.gradle
//build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 31
defaultConfig {
applicationId "com.example.cipher.myapplication"
minSdkVersion 22
targetSdkVersion 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
testImplementation 'junit:junit:4.+'
implementation 'net.zetetic:android-database-sqlcipher:3.5.9@aar'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
//Copy the following code into the newly created “EventDataSQLHelper.java”.
//EventDataSQLHelper
package com.example.cipher.myapplication;
import android.content.Context;
import android.provider.BaseColumns;
import android.util.Log;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteOpenHelper;
/**
* Created by Monkey on 11/19/2015.
*/
public class EventDataSQLHelper extends SQLiteOpenHelper{
private static final String DATABASE_NAME = "events.db";
private static final int DATABASE_VERSION = 1;
// Table name
public static final String TABLE = "events";
// Columns
public static final String TIME = "time";
public static final String TITLE = "title";
public EventDataSQLHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table " + TABLE + "( " + BaseColumns._ID
+ " integer primary key autoincrement, " + TIME + " integer, "
+ TITLE + " text not null);";
//Log.d("EventsData", "onCreate: " + sql);
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion >= newVersion)
return;
String sql = null;
if (oldVersion == 1)
sql = "alter table " + TABLE + " add note text;";
if (oldVersion == 2)
sql = "";
Log.d("EventsData", "onUpgrade : " + sql);
if (sql != null)
db.execSQL(sql);
}
}
//Copy and paste the code to activity_main.xml
//activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Running Successfully, next step you can change password to another string."
android:id="@+id/textView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="48dp" />
</RelativeLayout>
//Copy and paste 'menu_main.xml' and 'dimens.xml' under "Menu" and "Values" folder respectively
//menu_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity">
<item android:id="@+id/action_settings"
android:icon="@mipmap/ic_launcher_round"
android:title="Menu"
app:showAsAction="ifRoom"/>
</menu>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
Now, "Copy" the downloaded (from here) file and "Paste" it as "icudt4dl.zip" into "AndroidStudioProject--> MyApplication --> app-->src-->main-->Assets"
Save the project and run it on the AVD that shall show this interface. The password is matched so that this application will run successfully which is shown below.
If we change the password to "wrong" this time, the passwords are not match and the program isn't able to read information from the database, we can see the error information through the IDE.
Click here to download Libs_for_Android_SQLCipher
Full Database Encryption for SQLite: https://www.zetetic.net/sqlcipher/