Intereting Posts
Как очистить ложные ошибки в eclipse? Значение android: colorForeground Отключение контекстного меню на длинных нажатиях на Android Android – Вибрационное устройство не работает Как я могу обнаружить клик в приемнике onTouch? Android: проведите экран, чтобы открыть другое действие? Видео с прозрачностью на Android Использовать плагин Android DataBinding параллельно плагину GoogleServices Android получает текущую локаль, а не по умолчанию Могу ли я переопределить скрытый (но общедоступный) метод и вызвать его супер метод? Android отображает другое диалоговое окно из диалогового окна Как получить значок, связанный с определенной учетной записью, из AccountManager.getAccounts () Android: уведомление перестает обновляться, как только оно обновляется определенное количество раз на Kit-Kat Дополнительно по электронной почте – Предпочтения XML Android.text.format.DateFormat «HH» не распознается как с java.text.SimpleDateFormat

Шифрование базы данных Android

Android использует базу данных SQLite для хранения данных, мне нужно зашифровать базу данных SQLite, как это можно сделать? Я понимаю, что данные приложения являются частными. Однако мне нужно явно шифровать базу данных SQLite, которую использует мое приложение.

Solutions Collecting From Web of "Шифрование базы данных Android"

SQLCipher – это расширение SQLite, которое обеспечивает прозрачное 256-битное шифрование AES файлов базы данных.

Ранее sqlcipher, который является Open Source Full Database Encryption для SQLite, недоступен для Android. Но теперь он доступен как альфа-релиз для платформы Android. Разработчики обновили стандартное приложение Android Notepadbot для использования SQLCipher.

Так что это определенно лучший и самый простой вариант на данный момент.

Базы данных зашифрованы, чтобы предотвратить INDIRECT ATTACKS . Этот термин и классы: KeyManager.java , Crypto.java взяты из книги Sheran Gunasekera по безопасности приложений Android . Я рекомендую всю эту книгу читать.

INDIRECT ATTACKS так называются, потому что вирус не подходит сразу после вашего приложения. Вместо этого он идет после ОС Android. Цель состоит в том, чтобы скопировать все базы данных SQLite в надежде, что автор вируса сможет скопировать любую конфиденциальную информацию, хранящуюся там. Однако, если вы добавили еще один уровень защиты, все автор вирусов увидит искаженные данные. Давайте построим криптографическую библиотеку, которую мы можем использовать во всех наших приложениях. Начнем с создания краткого набора спецификаций:

  • Использует симметричные алгоритмы: наша библиотека будет использовать симметричный алгоритм или блочный шифр для шифрования и дешифрования наших данных. Мы остановимся на AES, хотя мы должны иметь возможность изменить это позже.

  • Использует фиксированный ключ: мы должны иметь возможность включать ключ, который мы можем хранить на устройстве, которое будет использоваться для шифрования и дешифрования данных.

  • Ключ, хранящийся на устройстве: ключ будет находиться на устройстве. Хотя это риск для нашего приложения с точки зрения прямых атак, этого достаточно, чтобы защитить нас от непрямых атак.

Начнем с нашего модуля управления ключами (см. Листинг 1 ). Поскольку мы планируем использовать фиксированный ключ, нам не нужно генерировать случайное, как это было в предыдущих примерах. Поэтому KeyManager выполняет следующие задачи:

  1. Принять ключ в качестве параметра (метод setId(byte[] data) )
  2. Примите вектор инициализации в качестве параметра (метод setIv(byte[] data) )
  3. Храните ключ внутри файла во внутреннем хранилище
  4. Извлеките ключ из файла во внутреннем хранилище (метод getId(byte[] data) )
  5. Извлеките IV из файла во внутреннем хранилище (метод getIv(byte[] data) )

(Листинг 1. Модуль KeyManager 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()); } } } 

Затем мы создаем модуль Crypto (см. Листинг 2 ). Этот модуль заботится о шифровании и расшифровке. Мы добавили к armorEncrypt() и armorDecrypt() чтобы упростить преобразование данных байтового массива в печатные данные Base64 и наоборот. Мы будем использовать алгоритм AES с использованием режима шифрования Cipher Block Chaining (CBC) и дополнения PKCS # 5 .

(Листинг 2. Криптографический модуль 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))); } } 

Вы можете включить эти два файла в любое из ваших приложений, которым требуется шифрование данных. Во-первых, убедитесь, что у вас есть значение для вашего ключа и вектора инициализации, а затем вызовите любой из методов шифрования или дешифрования данных, прежде чем хранить их. В листинге 3 и листинге 4 содержится просто пример приложений этих классов. Мы создаем Activity с 3 кнопками Encrypt, Decrypt, Delete; 1 EditText для ввода данных; 1 TextView для вывода данных.

(Листинг 3. Пример. 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 "); } }); } } 

(Листинг 4. Пример. 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> 

Если база данных будет небольшой, вы можете получить небольшую сумму безопасности, дешифруя весь файл до временного местоположения (а не на SD-карте), а затем повторно зашифровать, когда вы его закрыли. Проблемы: преждевременная смерть приложения, изображение призраков на носителях.

Немного лучшее решение для шифрования полей данных. Это вызывает проблему для предложений WHERE и ORDER BY. Если зашифрованные поля нужно индексировать для поиска эквивалентности, вы можете сохранить криптографический хэш поля и выполнить поиск. Но это не помогает в поиске диапазона или заказе.

Если вы хотите стать более привлекательным, вы можете вникать в Android NDK и взломать крипто в C-код для SQLite.

Учитывая все эти проблемы и частичные решения, вы уверены, что вам действительно нужна база данных SQL для приложения? Возможно, вам будет лучше с чем-то вроде файла, который содержит зашифрованный сериализованный объект.

У вас наверняка есть зашифрованная база данных SQLite на Android. Однако вы не можете сделать это с помощью классов, предоставленных Google.

Пара альтернатив:

  • Скомпилируйте свой собственный SQLite через NDK и включите кодек шифрования, например, wxSQLite3 (в комплект входит бесплатный бесплатный кодек)
  • SQLCipher теперь включает поддержку Android

http://sqlite-crypt.com/ может помочь вам создать зашифрованную базу данных, хотя я никогда не использовал ее на андроиде, возможно, с исходным кодом.

Litereplica поддерживает шифрование с использованием шифрования ChaCha.

Чача почти в 3 раза быстрее, чем AES на портативных устройствах на базе ARMv7.

Есть привязки для Android.

Для создания и открытия зашифрованной базы данных мы используем URI следующим образом:

 "file:/path/to/file.db?cipher=...&key=..."