【问题标题】:Decrypting an encrypted file corrupts the file? Android - Java解密加密文件会损坏文件吗?安卓 - 爪哇
【发布时间】:2015-10-13 19:09:52
【问题描述】:

我正在使用以下代码来加密/解密:

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;


public class CryptoUtils {
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES";

    public static void encrypt(String key, File inputFile, File outputFile)
            throws CryptoException {
        doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
    }

    public static void decrypt(String key, File inputFile, File outputFile)
            throws CryptoException {
        doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
    }

    private static void doCrypto(int cipherMode, String key, File inputFile,
                                 File outputFile) throws CryptoException {
        try {
            Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PAdding");
            cipher.init(cipherMode, secretKey);

            FileInputStream inputStream = new FileInputStream(inputFile);
            byte[] inputBytes = new byte[(int) inputFile.length()];
            inputStream.read(inputBytes);

            byte[] outputBytes = cipher.doFinal(inputBytes);

            FileOutputStream outputStream = new FileOutputStream(outputFile);
            outputStream.write(outputBytes);

            inputStream.close();
            outputStream.close();

        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException
                | InvalidKeyException | BadPaddingException
                | IllegalBlockSizeException | IOException ex) {
            throw new CryptoException("Error encrypting/decrypting file", ex);
        }
    }

    public static class CryptoException extends Exception {

        public CryptoException() {
        }

        public CryptoException(String message, Throwable throwable) {
            super(message, throwable);
        }
    }
}

我可以加密和解密视频文件。 但是,我无法播放由相同代码加密的解密文件。

原文件:http://www.megafileupload.com/hSTZ/a.mp4

加密文件:http://www.megafileupload.com/hSU2/encrypted-a.mp4

解密文件:http://www.megafileupload.com/hSU1/decrypted-final-a.mp4

解密文件的前 16 个字节与原始文件不同。长度是一样的。

【问题讨论】:

  • 我对 java 中的加密不是太强,尤其是在 Android 下,但我担心我没有看到你如何将 IV 从加密函数传递到解密函数。 CBC 模式使用该初始化向量来混淆加密输出的第一个块,因此即使使用相同的密钥,相同的纯文本也会产生完全不同的加密文本。如果您使用与加密时不同的 IV 进行解密,则解密将成功,但第一个块(16 个字节)将被加扰。尝试显式提供您的 IV(如果您愿意,可以对其进行硬编码以进行测试),看看是否可行。
  • 我没有提到我的怀疑,但是在C#的.NET中,如果你有CBC模式并且没有指定你的IV,算法会随机生成一个。通常,您会将其写为加密输出的第一个块,然后将其作为加密输入的第一个块读取,以用于准备解密算法。因此,要么将随机 IV 写入输出文件的开头,要么(仅用于测试)将其硬编码到程序中。请注意,硬编码的 IV 失去了 IV 提供的所有有益属性。但出于测试目的,我会尝试这样做。
  • 不知道你是如何加密的,就不可能知道解密代码有什么问题。我不想玩guessing game
  • @WDS 我已经下载了文件。事实上,错误的 IV 是问题所在,但目前的问题无法提供解决方案。
  • @ArtjomB。我怎样才能在那里添加盐代码..你能帮忙吗?谢谢

标签: java android encryption cryptography


【解决方案1】:

你假设:

  1. 文件适合内存。
  2. 文件大小适合 int。
  3. read() 填充缓冲区。
  4. 加密或解密的结果与源内容一起放入内存中。

不需要任何这些假设。

FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile);
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
    byte[] output = cipher.update(buffer, 0, count);
    outputStream.write(output);
}
outputStream.write(cipher.doFinal());
outputStream.close();
inputStream.close();

E&OE,但你明白了。使用CipherInput/OutputStreams, 可以让你的生活变得更简单,但这样你就会失去与加密异常的联系。

【讨论】:

  • 感谢@EJP 的帮助,但更改无效.. 解密后的加密文件无法播放..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-07
  • 1970-01-01
相关资源
最近更新 更多