Android używa bazy danych SQLite do przechowywania danych, muszę zaszyfrować bazę danych SQLite, jak to zrobić? Rozumiem, że dane aplikacji są prywatne. Jednak muszę jawnie zaszyfrować bazę danych SQLite, z której korzysta moja aplikacja.
android
database
sqlite
encryption
user121196
źródło
źródło
Bazy danych są szyfrowane, aby temu zapobiec
INDIRECT ATTACKS
. Ten termin i klasy: KeyManager.java , Crypto.java pochodzą z książki Sherana Gunasekera Android Apps Security . Polecam całą tę książkę do przeczytania.INDIRECT ATTACKS
są tak nazwane, ponieważ wirus nie atakuje bezpośrednio twojej aplikacji. Zamiast tego idzie po systemie operacyjnym Android. Celem jest skopiowanie wszystkich baz danych SQLite w nadziei, że autor wirusa będzie mógł skopiować wszelkie przechowywane w nich poufne informacje. Gdyby jednak dodać kolejną warstwę ochrony, wszystkie dane, które autor wirusa zobaczyłby, to zniekształcone dane. Zbudujmy bibliotekę kryptograficzną, której będziemy mogli ponownie wykorzystać we wszystkich naszych aplikacjach. Zacznijmy od stworzenia krótkiego zestawu specyfikacji:Wykorzystuje algorytmy symetryczne: Nasza biblioteka będzie używać algorytmu symetrycznego lub szyfru blokowego do szyfrowania i odszyfrowywania naszych danych. Zdecydujemy się na AES, chociaż powinniśmy być w stanie to zmienić w późniejszym terminie.
Używa stałego klucza: Musimy mieć możliwość dołączenia klucza, który możemy przechowywać na urządzeniu, który będzie używany do szyfrowania i odszyfrowywania danych.
Klucz przechowywany na urządzeniu: klucz będzie znajdował się na urządzeniu. Chociaż jest to zagrożenie dla naszej aplikacji z punktu widzenia ataków bezpośrednich, powinno wystarczyć do ochrony nas przed atakami pośrednimi.
Zacznijmy od naszego modułu zarządzania kluczami (patrz Listing 1 ). Ponieważ planujemy użyć stałego klucza, nie będziemy musieli generować losowego, jak to robiliśmy w poprzednich przykładach. Dlatego KeyManager wykona następujące zadania:
setId(byte[] data)
metoda)setIv(byte[] data)
metoda)getId(byte[] data)
metoda)getIv(byte[] data)
metoda)(Listing 1. Moduł KeyManager KeyManager.java )
Następnie wykonujemy moduł Crypto (patrz Listing 2 ). Ten moduł zajmuje się szyfrowaniem i deszyfrowaniem. Dodaliśmy metodę
armorEncrypt()
iarmorDecrypt()
do modułu, aby ułatwić konwersję danych tablicy bajtów na dane Base64 do wydrukowania i odwrotnie. Użyjemy algorytmu AES z trybem szyfrowania Cipher Block Chaining (CBC) i dopełnieniem PKCS # 5 .(Listing 2. Moduł kryptograficzny Crypto.java )
Możesz dołączyć te dwa pliki do dowolnej aplikacji, która wymaga szyfrowania danych. Najpierw upewnij się, że masz wartość klucza i wektora inicjalizacji, a następnie wywołaj dowolną z metod szyfrowania lub deszyfrowania danych przed ich zapisaniem. Listing 3 i Listing 4 zawierają prosty przykład aplikacji tych klas przy użyciu. Tworzymy działanie z 3 przyciskami Szyfruj, odszyfruj, usuń; 1 EditText do wprowadzania danych; 1 TextView do wyprowadzania danych.
(Listing 3. Przykład. 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. Przykład. 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>
źródło
Jeśli baza danych będzie mała, możesz uzyskać niewielką ochronę, odszyfrowując cały plik do tymczasowej lokalizacji (nie na karcie SD), a następnie ponownie zaszyfruj po zamknięciu. Problemy: przedwczesna śmierć aplikacji, obraz ducha na nośniku.
Nieco lepsze rozwiązanie do szyfrowania pól danych. Powoduje to problem z klauzulami WHERE i ORDER BY. Jeśli zaszyfrowane pola wymagają indeksowania w celu wyszukiwania równoważności, możesz zapisać kryptograficzny skrót pola i wyszukać go. Ale to nie pomaga w wyszukiwaniu zakresów lub porządkowaniu.
Jeśli chcesz stać się bardziej wyrafinowanym, możesz zagłębić się w Android NDK i zhakować trochę kryptowalut do kodu C dla SQLite.
Biorąc pod uwagę wszystkie te problemy i częściowe rozwiązania, czy na pewno potrzebujesz bazy danych SQL do aplikacji? Lepiej byłoby, gdybyś miał coś takiego jak plik, który zawiera zaszyfrowany obiekt serializowany.
źródło
Z pewnością możesz mieć zaszyfrowaną bazę danych SQLite na Androida. Nie możesz tego jednak zrobić, jeśli nie masz klas dostarczonych przez Google.
Kilka alternatyw:
źródło
http://sqlite-crypt.com/ może pomóc w utworzeniu zaszyfrowanej bazy danych, chociaż nigdy nie używałem jej na Androidzie, wydaje się, że jest to możliwe z kodem źródłowym.
źródło