我正在考虑为Android开发一个鸟类目录.它将包含许多图片和音频文件.所有这些文件都来自拥有版权的第三方公司.
我的应用程序应该(尽可能地)确保不能访问,复制或操纵这些媒体文件.
我可以遵循哪些策略?在文件系统中加密文件并在显示或播放之前在内存中解密?将它们作为CLOB保存到SQL Lite中?这个SQL Lite是否可以从其他应用程序访问,还是隐藏在其他应用程序中?还有其他想法吗?我没有在网上找到关于这个"问题"的太多信息.
提前致谢,
CHEMI.
我建议将这些文件保存到SD卡,而不是活动的私人文件,因为图像/音频文件通常很大(我在本次讨论中看到你计划处理400 MB,这是相同的应用程序吗? ).所以加密应该没问题,比SQLite更直接.
下面的类允许将字节加密为二进制文件:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AESEncrypter {
public static void encryptToBinaryFile(String password, byte[] bytes, File file) throws EncrypterException {
try {
final byte[] rawKey = getRawKey(password.getBytes());
final FileOutputStream ostream = new FileOutputStream(file, false);
ostream.write(encrypt(rawKey, bytes));
ostream.flush();
ostream.close();
} catch (IOException e) {
throw new EncrypterException(e);
}
}
public static byte[] decryptFromBinaryFile(String password, File file) throws EncrypterException {
try {
final byte[] rawKey = getRawKey(password.getBytes());
final FileInputStream istream = new FileInputStream(file);
final byte[] buffer = new byte[(int)file.length()];
istream.read(buffer);
return decrypt(rawKey, buffer);
} catch (IOException e) {
throw new EncrypterException(e);
}
}
private static byte[] getRawKey(byte[] seed) throws EncrypterException {
try {
final KeyGenerator kgen = KeyGenerator.getInstance("AES");
final SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
final SecretKey skey = kgen.generateKey();
return skey.getEncoded();
} catch (Exception e) {
throw new EncrypterException(e);
}
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws EncrypterException {
try {
final SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
final Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
return cipher.doFinal(clear);
} catch (Exception e) {
throw new EncrypterException(e);
}
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws EncrypterException {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
try {
final Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return cipher.doFinal(encrypted);
} catch (Exception e) {
throw new EncrypterException(e);
}
}
Run Code Online (Sandbox Code Playgroud)
}
您还需要此Exception类:
public class EncrypterException extends Exception {
public EncrypterException ( ) { super( ); }
public EncrypterException (String str ) { super(str); }
public EncrypterException (Throwable e) { super(e); }
}
Run Code Online (Sandbox Code Playgroud)
然后,您只需使用以下内容生成加密文件:
encryptToBinaryFile("password", bytesToSaveEncrypted, encryptedFileToSaveTo);
Run Code Online (Sandbox Code Playgroud)
在您的应用中,您可以通过以下方式阅读它们:
byte [] clearData = decryptFromBinaryFiles("password", encryptedFileToReadFrom);
Run Code Online (Sandbox Code Playgroud)
要使用硬编码密码,可以通过挖掘混淆代码并查找字符串来进行攻击.我不知道你的情况下这是否足够安全?
如果没有,您可以将密码存储在Activity的私人首选项中,或者使用诸如this.class.getDeclaredMethods()[n] .getName()之类的技巧作为密码.这更难找到.
关于表演,你必须知道加密/解密可能需要很长时间.这需要一些测试.
[编辑:04-25-2014]我的回答中有一个很大的错误.这种实现是播种SecureRandom,这是坏的(有些人会说'邪恶').
有一种简单的方法来规避这个问题.它详细说明这里在Android开发者博客.对于那个很抱歉.
| 归档时间: |
|
| 查看次数: |
1506 次 |
| 最近记录: |