Android加密大文件

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

我尝试加密和解密大型音频二进制文件。使用CipherInputStream和CipherOutputStream。我知道,关于这个主题存在很多问题。但我不明白我的代码出了什么问题。请清楚地描述错误。谢谢

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)的方案
这就是您不应该使用ECB模式的原因

(图片的答案)


(图片,见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();