Android加密大文件
我尝试加密和解密大型音频二进制文件。使用CipherInputStream和CipherOutputStream。我知道,关于这个主题存在很多问题。但我不明白我的代码出了什么问题。请清楚地描述错误。谢谢Android加密大文件,android,encryption,Android,Encryption,我尝试加密和解密大型音频二进制文件。使用CipherInputStream和CipherOutputStream。我知道,关于这个主题存在很多问题。但我不明白我的代码出了什么问题。请清楚地描述错误。谢谢 public void encrypt() { doCrypto(Cipher.ENCRYPT_MODE, KEY); } public void decrypt() { doCrypto(Cipher.DECRYPT_MODE, KEY); } private void d
public void encrypt() {
doCrypto(Cipher.ENCRYPT_MODE, KEY);
}
public void decrypt() {
doCrypto(Cipher.DECRYPT_MODE, KEY);
}
private void doCrypto(int cipherMode, String key) {
try {
Key secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(cipherMode, secretKey);
FileInputStream inputStream = new FileInputStream(this);
FileOutputStream fileOutputStream = new FileOutputStream(this);
int read;
CipherInputStream cis = new CipherInputStream(inputStream, cipher);
CipherOutputStream cos = new CipherOutputStream(fileOutputStream, cipher);
while ((read = cis.read()) != -1) {
cos.write(read);
cos.flush();
}
cos.close();
cis.close();
inputStream.close();
fileOutputStream.close();
} catch (NoSuchPaddingException | NoSuchAlgorithmException
| InvalidKeyException | IOException ex) {
throw new RuntimeException("Error encrypting/decrypting file", ex);
}
}
例外情况:
Caused by: java.lang.RuntimeException: Error encrypting/decrypting file at .hortext.HortextFile.doCrypto(HortextFile.java:81)
at .tools.hortext.HortextFile.decrypt(HortextFile.java:52)
at .tools.hortext.FilesStorage.getStringFromStorage(FilesStorage.java:104)
at com.msg.mobilinga.ui.ListenTextActivity.onCreate(ListenTextActivity.java:83)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.io.IOException: Error while finalizing cipher
at javax.crypto.CipherInputStream.fillBuffer(CipherInputStream.java:104)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:130)
at com.msg.mobilinga.tools.hortext.HortextFile.doCrypto(HortextFile.java:69)
at com.msg.mobilinga.tools.hortext.HortextFile.decrypt(HortextFile.java:52)
at com.msg.mobilinga.tools.hortext.FilesStorage.getStringFromStorage(FilesStorage.java:104)
at com.msg.mobilinga.ui.ListenTextActivity.onCreate(ListenTextActivity.java:83)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:894)
at javax.crypto.Cipher.doFinal(Cipher.java:1314)
at javax.crypto.CipherInputStream.fillBuffer(CipherInputStream.java:102)
at javax.crypto.CipherInputStream.read(CipherInputStream.java:130)
at com.msg.mobilinga.tools.hortext.HortextFile.doCrypto(HortextFile.java:69)
at com.msg.mobilinga.tools.hortext.HortextFile.decrypt(HortextFile.java:52)
at com.msg.mobilinga.tools.hortext.FilesStorage.getStringFromStorage(FilesStorage.java:104)
at com.msg.mobilinga.ui.ListenTextActivity.onCreate(ListenTextActivity.java:83)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
问题很可能是:
CipherInputStream cis = new CipherInputStream(inputStream, cipher);
CipherOutputStream cos = new CipherOutputStream(fileOutputStream, cipher);
您应该只使用其中一个。Cipher
保存一些状态,但是由于您将Cipher
传递给两个流,它们都将使用相同的状态,并且会发生不可预测的情况(技术术语:)
当然,如果使用缓冲区,性能会更好:
FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
int read;
byte[] buffer = new byte[4096];
CipherInputStream cis = new CipherInputStream(inputStream, cipher);
while ((read = cis.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
}
fileOutputStream.close();
cis.close();
请记住,您无法写入当前正在读取的文件。您必须使用两个文件
安全考虑:
- 始终使用完全限定的密码字符串<代码>Cipher.getInstance(“AES”)将根据默认值选择一些密码,这些密码很可能是
cipher.getInstance(“AES/ECB/PKCS5Padding”)代码>。默认值可能会更改,这将破坏您的代码
- 永远不要使用ECB模式,因为它不是
- CBC模式提供语义安全性,但仅适用于不可预测的(随机读取)IV。IV不必是机密的,因此您可以将其预编到密文中,并在解密之前切掉
- 验证密文可以防止许多攻击。您可以使用认证模式(如GCM或EAX),也可以应用具有强大MAC功能(如HMAC-SHA256)的方案
(图片,见abovr网址)@ArtjomB。编辑器看不到我的异常。我正在编辑这篇文章。请拿出你的负号。谢谢。除了逐字节读写、使用ECB模式和文本编码键之外,您的代码看起来还不错。划伤那个。。。为什么要同时使用
CipherInputStream
和CipherOutputStream
。嗯,你能告诉我该怎么做吗?谢谢。@ArtjomB。一个流读取编码解码,另一个写相同的文件与结果。你的答案是真的美丽。这个星球上一定有更多像你这样的人。但我有不同的问题,结果文件是空的。我不知道您的代码中有什么这个
,但我怀疑您为文件
创建了一个子类。在这种情况下,您无法写入当前正在读取的文件。是的,关于文件的子类,您是对的。你是说我的代码只读取,不写入文件?谢谢………需要用什么来做安全的二进制文件?你需要使用CBC模式。
FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
int read;
byte[] buffer = new byte[4096];
CipherInputStream cis = new CipherInputStream(inputStream, cipher);
while ((read = cis.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
}
fileOutputStream.close();
cis.close();