加密解密数据库文件在 Android 与 FileInputStream/密码

标签: sqlite Android
发布时间: 2016/10/10 22:41:40
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

密码/CipherInputStream 用于加密和解密的数据库 file(sqlite) Android 备份它。
当我使用没有密码 FileInputStream 时,效果很好。但是当我使用密码,文件加密成功,但是当我 decrypt(restore) 它,数据库不会解密到原始"源代码"。
原始的 caracteres(source code) 似乎是表意文字/象形文字/kanjis(I don't know),当我进行加密和解密,"源代码"是 sql(english) 恢复不错
这使得 '数据库损坏'

只是澄清

备份

File dbFile = new File(PATH_DB);

FileInputStream fileInputStream = new FileInputStream(PATH_DB);

FileOutputStream outputStream = new FileOutputStream(PATH_BKP);

byte[] s = Arrays.copyOf(KEY_DATABASE.getBytes(),16);
SecretKeySpec sks = new SecretKeySpec(s, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, sks);

CipherOutputStream cos = new CipherOutputStream(outputStream, cipher);

//Transferencia dos dados do inputfile para o output
byte[] buffer = new byte[1024];
int length;
while ((length = fileInputStream.read(buffer))!= -1) {
    cos.write(buffer,0,length);
}

//Fecha as streams
cos.flush();
cos.close();
fileInputStream.close();

还原︰

FileInputStream fis = new FileInputStream(PATH_BKP);

FileOutputStream fos = new FileOutputStream(PATH_DB);

byte[] s = Arrays.copyOf(KEY_DATABASE.getBytes(),16);
SecretKeySpec sks = new SecretKeySpec(s, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, sks);

CipherInputStream cis = new CipherInputStream (fis, cipher);

byte[] buffer = new byte[1024];
int length;
while ((length = cis.read(buffer)) != -1) {
    fos.write(buffer, 0, length);
}

fos.flush();
fos.close();
cis.close();

解决方法 1:

CBC 模式需要初始化向量 (IV) 操作。这四不是一个秘密的值,但却难以预测 (阅读︰ 随机选择)。为了使解密工作,你必须使用相同的四。否则,将损坏的第一个块。解决这个问题的常用方法是编写在密文前的四。

如果你调用 Cipher#init 没有 IvParameterSpec 作为第三个参数,第四将会为您自动生成。如果你不能保存它,它将会丢失。

加密过程中

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, sks);

outputStream.write(cipher.getIV()); // store the generated IV

CipherOutputStream cos = new CipherOutputStream(outputStream, cipher);

解密过程中

byte[] iv = new byte[16]; // 16 is the block size of AES
if (fis.read(iv) != 16) {
    throw new Exception("Incomplete IV"); // TODO: rename to a different exception
}

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, sks, new IvParameterSpec(iv));

CipherInputStream cis = new CipherInputStream (fis, cipher);
官方微信
官方QQ群
31647020