Android usa la base de datos SQLite para almacenar datos, necesito cifrar la base de datos SQLite, ¿cómo se puede hacer esto? Entiendo que los datos de la aplicación son privados. Sin embargo, necesito cifrar explícitamente la base de datos SQLite que está usando mi aplicación.
fuente
Las bases de datos están encriptadas para prevenir
INDIRECT ATTACKS
. Este término y las clases: KeyManager.java , Crypto.java se toman del libro de Sheran Gunasekera Android Apps Security . Recomiendo todo este libro a la lectura.INDIRECT ATTACKS
se llaman así, porque el virus no ataca directamente a su aplicación. En cambio, va tras el sistema operativo Android. El objetivo es copiar todas las bases de datos SQLite con la esperanza de que el autor del virus pueda copiar cualquier información confidencial almacenada allí. Sin embargo, si hubiera agregado otra capa de protección, todo lo que el autor del virus vería son datos confusos. Construyamos una biblioteca criptográfica que podamos reutilizar en todas nuestras aplicaciones. Comencemos creando un breve conjunto de especificaciones:Utiliza algoritmos simétricos: nuestra biblioteca utilizará un algoritmo simétrico, o cifrado en bloque, para cifrar y descifrar nuestros datos. Nos decidiremos por AES, aunque deberíamos poder modificarlo en una fecha posterior.
Utiliza una clave fija: Necesitamos poder incluir una clave que podamos almacenar en el dispositivo que se utilizará para cifrar y descifrar datos.
Clave almacenada en el dispositivo: la clave residirá en el dispositivo. Si bien esto es un riesgo para nuestra aplicación desde la perspectiva de los ataques directos, debería ser suficiente para protegernos contra ataques indirectos.
Comencemos con nuestro módulo de administración de claves (ver Listado 1 ). Debido a que planeamos usar una clave fija, no necesitaremos generar una aleatoria como hicimos en los ejemplos anteriores. Por lo tanto, KeyManager realizará las siguientes tareas:
setId(byte[] data)
método)setIv(byte[] data)
método)getId(byte[] data)
método)getIv(byte[] data)
método)(Listado 1. El módulo KeyManager KeyManager.java )
A continuación, hacemos el módulo Crypto (ver Listado 2 ). Este módulo se encarga del cifrado y descifrado. Hemos agregado un método
armorEncrypt()
yarmorDecrypt()
al módulo para facilitar la conversión de los datos de la matriz de bytes en datos Base64 imprimibles y viceversa. Usaremos el algoritmo AES con el modo de cifrado Cipher Block Chaining (CBC) y relleno PKCS # 5 .(Listado 2. El módulo criptográfico Crypto.java )
Puede incluir estos dos archivos en cualquiera de sus aplicaciones que requieran que el almacenamiento de datos esté cifrado. Primero, asegúrese de tener un valor para su clave y vector de inicialización, luego llame a cualquiera de los métodos de cifrado o descifrado de sus datos antes de almacenarlos. El Listado 3 y el Listado 4 contienen un simple ejemplo de aplicación de estas clases usando. Creamos una Actividad con 3 Botones Cifrar, Descifrar, Eliminar; 1 EditText para la entrada de datos; 1 TextView para salida de datos.
(Listado 3. Un ejemplo. 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 "); } }); } }
(Listado 4. Un ejemplo. 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>
fuente
Si la base de datos será pequeña, entonces puede obtener una pequeña cantidad de seguridad descifrando todo el archivo en una ubicación temporal (no en la tarjeta SD) y luego volviendo a cifrar cuando lo haya cerrado. Problemas: muerte prematura de la aplicación, imagen fantasma en los medios.
Una solución ligeramente mejor para cifrar los campos de datos. Esto causa un problema para las cláusulas WHERE y ORDER BY. Si los campos encriptados deben indexarse para la búsqueda de equivalencia, entonces puede almacenar un hash criptográfico del campo y buscarlo. Pero eso no ayuda con las búsquedas de rango o los pedidos.
Si desea ser más elegante, puede profundizar en el NDK de Android y piratear algunas criptomonedas en el código C para SQLite.
Teniendo en cuenta todos estos problemas y soluciones parciales, ¿está seguro de que realmente necesita una base de datos SQL para la aplicación? Es posible que esté mejor con algo como un archivo que contiene un objeto serializado cifrado.
fuente
Sin duda, puede tener una base de datos SQLite cifrada en Android. Sin embargo, no puede hacerlo con las clases listas para usar proporcionadas por Google.
Un par de alternativas:
fuente
http://sqlite-crypt.com/ puede ayudarlo a crear una base de datos encriptada, aunque nunca la he usado en Android parece ser posible con el código fuente.
fuente