Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 359 Vote(s) - 3.58 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Android database encryption

#1
Android uses SQLite database to store data, I need to encrypt the SQLite database, how can this be done? I understand that application data is private. However I need to explictly encrypt the SQLite database that my app is using.
Reply

#2
If the database will be small, then you could gain a small amount of security by decrypting the whole file to a temp location (not on sd card), then re-encrypting when you've closed it. Problems: premature app death, ghost image on media.

A slightly better solution to encrypt the data fields. This causes a problem for WHERE and ORDER BY clauses. If the encrypted fields need to be indexed for equivalence searching, then you can store a cryptographic hash of the field and search for that. But that doesn't help with range searches or ordering.

If you want to get fancier, you could delve into the Android NDK and hack some crypto into C code for SQLite.

Considering all these problems and partial solutions, are you sure you really need a SQL database for the application? You might be better off with something like a file that contains an encrypted serialized object.
Reply

#3
You can certainly have a encrypted SQLite database on Android. You can't do it with the out of the box Google provided classes, however.

**A couple alternatives:**

- Compile your own SQLite via the NDK and include the encryption codec from for example, [wxSQLite3][1] (a nice free codec is included in the package)
- [SQLCipher][2] now includes support for Android

[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#4
Databases are encrypted in order to prevent `INDIRECT ATTACKS`.
This term and classes: *KeyManager.java*, *Crypto.java* are taken from *Sheran Gunasekera* book [Android Apps Security][4]. I recommend all this book to reading.

`INDIRECT ATTACKS` are so named, because the virus does not go after your application directly. Instead, it goes after the Android OS. The aim is to copy all SQLite databases in the hopes that the virus author can copy any sensitive information stored there. If you had added another layer of protection, however, then all the virus author would see is garbled data.
Let’s build a cryptographic library that we can reuse in all our applications. Let’s start by creating a brief set of specifications:

- Uses symmetric algorithms: Our library will use a symmetric algorithm,
or block cipher, to encrypt and decrypt our data. We will settle on AES,
although we should be able to modify this at a later date.

- Uses a fixed key: We need to be able to include a key that we can store on
the device that will be used to encrypt and decrypt data.

- Key stored on device: The key will reside on the device. While this is a risk
to our application from the perspective of direct attacks, it should suffice in
protecting us against indirect attacks.

Let’s start with our key management module (see **Listing 1**). Because we plan to use a fixed key, we won’t need to generate a random one as we did in the past examples. The *KeyManager* will therefore perform the following tasks:

1. Accept a key as a parameter (the `setId(byte[] data)` method)
2. Accept an initialization vector as a parameter (the `setIv(byte[] data)`
method)
3. Store the key inside a file in the internal store
4. Retrieve the key from a file in the internal store (the `getId(byte[] data)`
method)
5. Retrieve the IV from a file in the internal store (the `getIv(byte[] data)`
method)

**(Listing 1. The KeyManager Module *KeyManager.java*)**

package com.yourapp.android.crypto;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.content.Context;
import android.util.Log;

public class KeyManager {

private static final String TAG = "KeyManager";
private static final String file1 = "id_value";
private static final String file2 = "iv_value";
private static Context ctx;

public KeyManager(Context cntx) {
ctx = cntx;
}

public void setId(byte[] data){
writer(data, file1);
}

public void setIv(byte[] data){
writer(data, file2);
}

public byte[] getId(){
return reader(file1);
}

public byte[] getIv(){
return reader(file2);
}

public byte[] reader(String file){
byte[] data = null;
try {
int bytesRead = 0;
FileInputStream fis = ctx.openFileInput(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
while ((bytesRead = fis.read(b)) != -1){
bos.write(b, 0, bytesRead);
}
data = bos.toByteArray();
} catch (FileNotFoundException e) {
Log.e(TAG, "File not found in getId()");
} catch (IOException e) {
Log.e(TAG, "IOException in setId(): " + e.getMessage());
}
return data;
}

public void writer(byte[] data, String file) {
try {
FileOutputStream fos = ctx.openFileOutput(file,
Context.MODE_PRIVATE);
fos.write(data);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e(TAG, "File not found in setId()");
} catch (IOException e) {
Log.e(TAG, "IOException in setId(): " + e.getMessage());
}
}
}

Next, we do the *Crypto* module (see **Listing 2**). This module takes care of the encryption and decryption. We have added an `armorEncrypt()` and `armorDecrypt()` method to the module to make it easier to convert the byte array data into printable [Base64][5] data and vice versa. We will use the [AES][3] algorithm with [Cipher Block Chaining (CBC) encryption mode][1] and [PKCS#5 padding][2].

**(Listing 2. The Cryptographic Module *Crypto.java*)**

package com.yourapp.android.crypto;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import android.content.Context;
import android.util.Base64;

public class Crypto {

private static final String engine = "AES";
private static final String crypto = "AES/CBC/PKCS5Padding";
private static Context ctx;
public Crypto(Context cntx) {
ctx = cntx;
}

public byte[] cipher(byte[] data, int mode) throws NoSuchAlgorithmException,NoSuchPaddingException,InvalidKeyException,IllegalBlockSizeException,BadPaddingException,InvalidAlgorithmParameterException {
KeyManager km = new KeyManager(ctx);
SecretKeySpec sks = new SecretKeySpec(km.getId(), engine);
IvParameterSpec iv = new IvParameterSpec(km.getIv());
Cipher c = Cipher.getInstance(crypto);
c.init(mode, sks, iv);
return c.doFinal(data);
}

public byte[] encrypt(byte[] data) throws InvalidKeyException,
NoSuchAlgorithmException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException {
return cipher(data, Cipher.ENCRYPT_MODE);
}

public byte[] decrypt(byte[] data) throws InvalidKeyException,
NoSuchAlgorithmException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException {
return cipher(data, Cipher.DECRYPT_MODE);
}

public String armorEncrypt(byte[] data) throws InvalidKeyException,NoSuchAlgorithmException,
NoSuchPaddingException,IllegalBlockSizeException,
BadPaddingException,InvalidAlgorithmParameterException {
return Base64.encodeToString(encrypt(data), Base64.DEFAULT);
}

public String armorDecrypt(String data) throws InvalidKeyException,NoSuchAlgorithmException,
NoSuchPaddingException,IllegalBlockSizeException,
BadPaddingException,InvalidAlgorithmParameterException {
return new String(decrypt(Base64.decode(data, Base64.DEFAULT)));
}
}

You can include these two files in any of your applications that require data storage to be encrypted. First, make sure that you have a value for your key and initialization vector, then call any one of the encrypt or decrypt methods on your data before you store it. **Listing 3** and **Listing 4** contain an simply App-example of these classes using. We create an Activity with 3 Buttons Encrypt, Decrypt, Delete; 1 EditText for data input; 1 TextView for data output.


**(Listing 3. An example. *MainActivity.java*)**

package com.yourapp.android.crypto;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


public class MainActivity extends Activity {
TextView encryptedDataView;
EditText editInputData;
private Context cntx;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.cntx = getApplicationContext();
Button btnEncrypt = (Button) findViewById(R.id.buttonEncrypt);
Button btnDecrypt = (Button) findViewById(R.id.buttonDecrypt);
Button btnDelete = (Button) findViewById(R.id.buttonDelete);
editInputData = (EditText)findViewById(R.id.editInputData) ;
encryptedDataView = (TextView) findViewById(R.id.encryptView);

/**********************************************/
/** INITIALIZE KEY AND INITIALIZATION VECTOR **/
String key = "12345678909876543212345678909876";
String iv = "1234567890987654";
KeyManager km = new KeyManager(getApplicationContext());
km.setIv(iv.getBytes());
km.setId(key.getBytes());
/**********************************************/

btnEncrypt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String Data = editInputData.getText().toString();
String Encrypted_Data = "data";
try {
Crypto crypto = new Crypto(cntx);
Encrypted_Data = crypto.armorEncrypt(Data.getBytes());
} catch (InvalidKeyException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
} catch (NoSuchPaddingException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
} catch (IllegalBlockSizeException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
} catch (BadPaddingException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
} catch (InvalidAlgorithmParameterException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
}
encryptedDataView.setText(Encrypted_Data);
}
});

btnDecrypt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String Data = encryptedDataView.getText().toString();
String Decrypted_Data = "data";
try {
Crypto crypto = new Crypto(cntx);
Decrypted_Data = crypto.armorDecrypt(Data);
} catch (InvalidKeyException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
} catch (NoSuchPaddingException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
} catch (IllegalBlockSizeException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
} catch (BadPaddingException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
} catch (InvalidAlgorithmParameterException e) {
Log.e("SE3", "Exception in StoreData: " + e.getMessage());
}
encryptedDataView.setText(Decrypted_Data);
}
});

btnDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
encryptedDataView.setText(" Deleted ");
}
});

}

}

**(Listing 4. An example. 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:background="#363636"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<EditText
android:id="@+id/editInputData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:ems="10"
android:textColor="#FFFFFF" >

<requestFocus />
</EditText>

<TextView
android:id="@+id/encryptView"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:layout_alignLeft="@+id/editInputData"
android:layout_alignRight="@+id/editInputData"
android:layout_below="@+id/buttonEncrypt"
android:layout_marginTop="26dp"
android:background="#000008"
android:text="Encrypted/Decrypted Data View"
android:textColor="#FFFFFF"
android:textColorHint="#FFFFFF"
android:textColorLink="#FFFFFF" />

<Button
android:id="@+id/buttonEncrypt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/encryptView"
android:layout_alignRight="@+id/editInputData"
android:layout_below="@+id/editInputData"
android:layout_marginTop="26dp"
android:text="Encrypt" />

<Button
android:id="@+id/buttonDelete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/buttonDecrypt"
android:layout_alignRight="@+id/buttonDecrypt"
android:layout_below="@+id/buttonDecrypt"
android:layout_marginTop="15dp"
android:text="Delete" />

<Button
android:id="@+id/buttonDecrypt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/encryptView"
android:layout_alignRight="@+id/encryptView"
android:layout_below="@+id/encryptView"
android:layout_marginTop="21dp"
android:text="Decrypt" />

</RelativeLayout>

[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

[4]:

[To see links please register here]

[5]:

[To see links please register here]

Reply

#5
I have used strong RSA encryption for individual database fields that do not require indexing. Search is never done by phone number, email, card number. It took one day. RSA uses a 2048 bit key. Breaking such code is much more difficult. I have done the export of the encrypted database and the obfuscation for the private key.
Reply

#6
<h1>Use SQLCipher</h1>

You have a two main options for using SQLCipher for Android in your app:

Using it with Room or other consumers of the androidx.sqlite API

Using the native SQLCipher for Android classes

In both cases, you will need to add a dependency on net.zetetic:android-database-sqlcipher, such as having the following line in your module's build.gradle dependencies closure:

implementation "net.zetetic:android-database-sqlcipher:4.5.2"
implementation "androidx.sqlite:sqlite:2.0.1"

[To see links please register here]

Reply

#7
See [SQLCipher](

[To see links please register here]

) —

> SQLCipher is an SQLite extension that provides transparent 256-bit AES encryption of database files

Earlier sqlcipher which is Open Source Full Database Encryption for SQLite was not available for android. But now it's available as alpha release for android platform.
Developers have updated the standard android application 'Notepadbot' to use SQLCipher.

So this is definitely the best and simplest option as of now.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through