使用FileInputStream/Cipher在Android中加密/解密数据库文件

使用FileInputStream/Cipher在Android中加密/解密数据库文件,android,sqlite,encryption,cryptography,Android,Sqlite,Encryption,Cryptography,我正在使用Cipher/CipherInputStream对Android中的数据库文件(sqlite)进行加密和解密以进行备份。 当我使用不带密码的FileInputStream时,它工作得非常好。但是当我使用密码时,文件加密成功,但当我解密(还原)它时,数据库不会解密为原始的“源代码” 原始字符(源代码)似乎是一个表意文字/象形文字/汉字(我不知道),当我加密和解密时,“源代码”是sql(英语)还原的O.O 这使得“数据库损坏” 只是为了澄清 备份 File dbFile=新文件(路径为DB

我正在使用Cipher/CipherInputStream对Android中的数据库文件(sqlite)进行加密和解密以进行备份。
当我使用不带密码的FileInputStream时,它工作得非常好。但是当我使用密码时,文件加密成功,但当我解密(还原)它时,数据库不会解密为原始的“源代码”
原始字符(源代码)似乎是一个表意文字/象形文字/汉字(我不知道),当我加密和解密时,“源代码”是sql(英语)还原的O.O
这使得“数据库损坏”

只是为了澄清

备份

File dbFile=新文件(路径为DB);
FileInputStream FileInputStream=新的FileInputStream(路径\ DB);
FileOutputStream outputStream=新的FileOutputStream(路径_BKP);
byte[]s=Arrays.copyOf(KEY_DATABASE.getBytes(),16);
SecretKeySpec sks=新的SecretKeySpec(s,“AES”);
Cipher Cipher=Cipher.getInstance(“AES/CBC/PKCS5PADDING”);
cipher.init(cipher.ENCRYPT_模式,sks);
CipherOutputStream cos=新的CipherOutputStream(outputStream,cipher);
//Transferncia dos dados do输入文件参数输出
字节[]缓冲区=新字节[1024];
整数长度;
而((长度=fileInputStream.read(缓冲区))!=-1){
cos.write(缓冲区,0,长度);
}
//Fecha as溪流
cos.flush();
cos.close();
fileInputStream.close();
恢复:

FileInputStream fis=新的FileInputStream(路径\u BKP);
FileOutputStream fos=新的FileOutputStream(路径\ DB);
byte[]s=Arrays.copyOf(KEY_DATABASE.getBytes(),16);
SecretKeySpec sks=新的SecretKeySpec(s,“AES”);
Cipher Cipher=Cipher.getInstance(“AES/CBC/PKCS5PADDING”);
cipher.init(cipher.DECRYPT_模式,sks);
CipherInputStream cis=新的CipherInputStream(fis,密码);
字节[]缓冲区=新字节[1024];
整数长度;
而((长度=CI.read(缓冲区))!=-1){
fos.写入(缓冲区,0,长度);
}
fos.flush();
fos.close();
cis.close();

CBC模式需要一个初始化向量(IV)来运行。这个IV不是一个秘密值,但它必须是不可预测的(读:随机选择)。为了使解密工作,您必须使用相同的IV。否则,第一个块将被损坏。解决这个问题的一个常见方法是在密文前面写IV

如果在没有IvParameterSpec作为第三个参数的情况下调用
Cipher#init
,IV将自动为您生成。如果你不储存它,它就会丢失

加密期间

Cipher-Cipher=Cipher.getInstance(“AES/CBC/PKCS5PADDING”);
cipher.init(cipher.ENCRYPT_模式,sks);
outputStream.write(cipher.getIV());//存储生成的IV
CipherOutputStream cos=新的CipherOutputStream(outputStream,cipher);
在解密过程中

byte[]iv=新字节[16];//16是AES的块大小
如果(第六读(四)!=16){
抛出新异常(“不完整IV”);//TODO:重命名为其他异常
}
Cipher Cipher=Cipher.getInstance(“AES/CBC/PKCS5PADDING”);
cipher.init(cipher.DECRYPT_模式,sks,新的IvParameterSpec(iv));
CipherInputStream cis=新的CipherInputStream(fis,密码);

CBC模式需要一个初始化向量(IV)来运行。这个IV不是一个秘密值,但它必须是不可预测的(读:随机选择)。为了使解密工作,您必须使用相同的IV。否则,第一个块将被损坏。解决这个问题的一个常见方法是在密文前面写IV

如果在没有IvParameterSpec作为第三个参数的情况下调用
Cipher#init
,IV将自动为您生成。如果你不储存它,它就会丢失

加密期间

Cipher-Cipher=Cipher.getInstance(“AES/CBC/PKCS5PADDING”);
cipher.init(cipher.ENCRYPT_模式,sks);
outputStream.write(cipher.getIV());//存储生成的IV
CipherOutputStream cos=新的CipherOutputStream(outputStream,cipher);
在解密过程中

byte[]iv=新字节[16];//16是AES的块大小
如果(第六读(四)!=16){
抛出新异常(“不完整IV”);//TODO:重命名为其他异常
}
Cipher Cipher=Cipher.getInstance(“AES/CBC/PKCS5PADDING”);
cipher.init(cipher.DECRYPT_模式,sks,新的IvParameterSpec(iv));
CipherInputStream cis=新的CipherInputStream(fis,密码);