Android使用SQLite数据库存储数据,我需要加密SQLite数据库,这怎么办呢?我了解,应用程序数据是私人的。不过,我需要明确地加密我的应用程序正在使用的SQLite数据库。Android数据库加密
回答
http://sqlite-crypt.com/可能会帮助你创建一个加密的数据库,虽然我从来没有用过它在android上似乎有可能与源代码。
如果数据库很小,那么可以通过将整个文件解密到一个临时位置(不在SD卡上),然后在关闭它时重新进行加密,从而获得一小部分安全性。问题:应用程序过早死亡,媒体上的鬼影。
稍微好一点的解决方案来加密数据字段。这会导致WHERE和ORDER BY子句出现问题。如果加密字段需要为等价搜索建立索引,则可以存储该字段的加密哈希并搜索该字段。但是这对范围搜索或排序没有帮助。
如果你想更有趣,你可以深入研究Android NDK,并将一些加密技术转换为SQLite的C代码。
考虑到所有这些问题和部分解决方案,你确定你确实需要一个SQL数据库的应用程序?您可能会更喜欢使用包含加密序列化对象的文件。
SQLCipher是一种SQLite扩展,它提供对数据库文件的透明256位AES加密。
以前的sqlcipher是SQLite的开源完整数据库加密不适用于android。但现在它可以作为Android平台的alpha版本。 开发人员已将标准android应用程序'Notepadbot'更新为使用SQLCipher。
所以这绝对是目前最好的和最简单的选项。
SQLCIpher for Android现在是SQLCipher官方项目的一部分:http://sqlcipher.net/sqlcipher-for-android/ – 2012-09-06 07:37:48
是免费使用还是必须购买许可证?我找不到准确的信息..:S – Ewoks 2012-11-16 12:40:46
许可证信息可在github页面上获得https://github.com/sqlcipher/android-database-sqlcipher/blob/master/LICENSE – vaichidrewar 2012-11-16 15:56:18
数据库被加密以防止INDIRECT ATTACKS
。 这个词和类:KeyManager.java,Crypto.java从Sheran Gunasekera书Android Apps Security拍摄。我推荐所有这本书阅读。
INDIRECT ATTACKS
之所以如此命名,是因为该病毒并没有申请后直接去。相反,它追随Android操作系统。其目的是将所有SQLite数据库复制,病毒作者可以复制存储有任何敏感信息的希望。如果您添加了另一个保护层,但是,那么所有的病毒作者将看到的是乱码数据。 让我们建立,我们可以在我们所有的应用程序重复使用的密码库。让我们创建一个简单的一套规范入手:
使用对称算法:我们的图书馆将使用对称算法, 或块密码,加密和解密我们的数据。我们将在AES, 解决,但我们应该能够在以后修改。
使用固定密钥:我们需要能够包含一个密钥,我们可以在 上存储将用于加密和解密数据的设备。
存储在设备上的密钥:密钥将驻留在设备上。虽然从直接攻击的角度来看,这对我们的应用来说是一个风险 ,但它应该足以在 保护我们免受间接攻击。
让我们开始我们的密钥管理模块(见清单1)。因为我们打算使用固定密钥,所以我们不需要像过去的例子那样生成一个随机密钥。因此,的KeyManager将执行以下任务:
- 接受一个密钥作为参数(
setId(byte[] data)
方法) - 接受一个初始化向量作为参数(
setIv(byte[] data)
方法) - 存储密钥在内部存储的文件中
- 从内部存储中的文件检索密钥(
getId(byte[] data)
方法) - 检索从文件中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());
}
}
}
接下来,我们做加密模块(参见列表2)。该模块负责加密和解密。我们已经将armorEncrypt()
和armorDecrypt()
方法添加到模块中,以便将字节数组数据转换为可打印的Base64数据,反之亦然。我们将使用AES算法与Cipher Block Chaining (CBC) encryption mode和PKCS#5 padding。
(清单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包含这些类使用的简单应用程序示例。我们用3个按钮创建一个活动加密,解密,删除; 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>
,加密有什么好处使用该密钥加密数据? – minhaz 2016-03-06 05:07:57
litereplica使用支持encryption ChaCha密码。
Chacha与基于ARMv7的便携式设备上的AES几乎相比3 times faster。
Android版本有bindings。
要创建并打开我们使用URI这样一个加密的数据库:
"file:/path/to/file.db?cipher=...&key=..."
- 1. Android加密数据库
- 2. 加密 - 解密,数据库
- 3. 在Android中加密数据库文件
- 4. 如何加密android sqlite数据库?
- 5. 加密数据库
- 6. 加密数据库
- 7. 加密/解密数据到数据库
- 8. “文件被加密或不是数据库”当尝试解密加密数据库时出现错误android
- 9. 加密的SQL数据库?
- 10. MongoDB数据库加密
- 11. 数据库列加密postgres
- 12. 数据库加密问题
- 13. .net加密数据库表
- 14. SQLite数据库加密C#?
- 15. 数据库加密问题
- 16. 加密数据库内容
- 17. 加密在MySQL数据库
- 18. 加密领域数据库
- 19. 加密整个数据库
- 20. 2路数据库加密
- 21. 加密数据库字段
- 22. 数据库加密 - php/mysql
- 23. 加密访问数据库
- 24. 加密MonetDB数据库
- 25. 加密数据库凭证
- 26. SQLite数据库加密
- 27. Rails加密SQL Server数据库database.yml中的数据库密码
- 28. 数据库加密和数据库解密使用C#代码
- 29. 加密密码并存储在数据库中android
- 30. 如何在Android上保护数据库(加密)密码?
我已加密的所有值甚至主键和解密。它慢,但它的工作。什么是最佳方案。 – 2011-02-24 09:40:33