【问题标题】:Encrypt and Decrypt files加密和解密文件
【发布时间】:2016-01-21 04:14:20
【问题描述】:

我需要下载 mp3 文件,必要时加密,以解密临时 mp3 并收听。

用作参考这个答案已经在 StackOverflow 中完成

Encrypting files with AES on Android

所有步骤都有效。但是当我为 MediaPlayer 发送生成的 mp3 文件时无法识别和中断。

这些是我的下载和加密方法

 public void executeAsyncDownload(String urlFile, String id, int position, HandlerCallback callback) {

    String encryptedName = Cypher.md5(id);

    if (MediaUtils.containsFile(encryptedName)) {
        callback.onDownloadFinish(position);
        return;
    }

    File dir = MediaUtils.getDestinationFolder(destination);

    if (!dir.exists()) {
        dir.mkdir();
    }

    try {
        if (canceled)
            return;

        callback.onDownloadStart(position);
        URL url = new URL(urlFile);
        URLConnection connection = url.openConnection();
        connection.connect();
        int tamFile = connection.getContentLength();
        String filePath = MediaUtils.getFilePath(MediaUtils.tempPath + encryptedName).toString();

        InputStream fis = new BufferedInputStream(url.openStream());
        OutputStream fos = new FileOutputStream(filePath);
        File file = new File(filePath);

        byte data[] = new byte[80192];
        int count;
        long total = 0;

        while ((count = fis.read(data)) != -1) {
            total += count;
            if (tamFile > 0) {
                int percentage = (int) (total * 100 / tamFile);
                if (percentage % 20 == 0)
                    callback.onDownloadProgress(percentage, position);
            }

            fos.write(data, 0, count);

            if (canceled) {
                MediaUtils.deleteFile(file);
                return;
            }
        }


        if (canceled)
            return;


        byte[] key = (salt + cryptPassword).getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 8);
        SecretKeySpec sks = new SecretKeySpec(key, "DES");
        Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, sks);
        CipherOutputStream cos = new CipherOutputStream(fos, cipher);

        int b;
        byte[] d = new byte[8192];
        while ((b = fis.read(d)) != -1) {
            cos.write(d, 0, b);
        }

        OutputStream outputEncrypted = new FileOutputStream(dir + File.separator + encryptedName);
        outputEncrypted.write(d);
        outputEncrypted.close();


        fos.flush();
        fos.close();
        fis.close();

        MediaUtils.deleteFile(file);//delete temp file

        callback.onDownloadFinish(position);
    } catch (Exception e) {
        e.printStackTrace();
        callback.onDownloadError(position);
    }
}

这是我的解密方法

 @SafeVarargs
@Override
protected final File doInBackground(HashMap<String, Object>... params) {
    String path = (String) params[0].get(FILE_PATH);
    String fileName = String.valueOf(params[0].get(FILE_NAME));
    boolean encrypted = (boolean) params[0].get(ENCRYPTED);

    File root = android.os.Environment.getExternalStorageDirectory();
    File dir = new File(root.getAbsolutePath() + File.separator + path + File.separator);
    File file;

    if (!encrypted) {
        file = new File(dir + File.separator + fileName);
        return file;
    }

    file = new File(dir + File.separator + Cypher.md5(fileName));
    File tempMp3 = null;
    try {
        tempMp3 = File.createTempFile(TEMP, MP3, context.getCacheDir());
        tempMp3.deleteOnExit();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        FileInputStream fis = new FileInputStream(file);
        byte[] key = (DownloadManager.salt + DownloadManager.cryptPassword).getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 8);
        SecretKeySpec sks = new SecretKeySpec(key, "DES");
        Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, sks);
        CipherInputStream cis = new CipherInputStream(fis, cipher);

        FileOutputStream fos = new FileOutputStream(tempMp3);

        int b;
        byte[] d = new byte[80192];
        while ((b = cis.read(d)) != -1) {
            fos.write(d, 0, b);
        }

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

    } catch (IOException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }

    return tempMp3;
}

【问题讨论】:

  • @petey 问题是解密生成的mp3文件不起作用。不陷入异常,在加解密时不崩溃。只需解密即可生成 MediaPlayer 无法读取的文件。加密前的mp3文件有效,但解密后的mp3不行

标签: java android encryption cryptography


【解决方案1】:

您的加密或解密方法似乎有错字。

在加密中:

    int b;
    byte[] d = new byte[8192];
    while ((b = cis.read(d)) != -1) {
        fos.write(d, 0, b);
    }

在解密中:

    int b;
    byte[] d = new byte[80192];
    while ((b = cis.read(d)) != -1) {
        fos.write(d, 0, b);
    }

解密时的字节数组 d 比加密时的字节数组大 10 倍左右。

【讨论】:

  • 虽然这有点奇怪,但它是如何导致上述问题的呢?
  • 如果文件末尾有 72K 未初始化的字节,可能会导致无法读取。不是 mp3 专家,但似乎有可能。
  • @PunDefeated 忽略8后的0,真的是8192。这个80192是最后一次尝试增加字节数
【解决方案2】:

这样做之后:

    CipherOutputStream cos = new CipherOutputStream(fos, cipher);

    int b;
    byte[] d = new byte[8192];
    while ((b = fis.read(d)) != -1) {
        cos.write(d, 0, b);
    }

    OutputStream outputEncrypted = new FileOutputStream(dir + File.separator + encryptedName);
    outputEncrypted.write(d);
    outputEncrypted.close();

outputEncrypted 文件将只包含最后一个充满数据的缓冲区。此外,这些数据不会被加密。

【讨论】:

  • 解释得更好。我不明白
  • 在最后 3 行中打开一个新流,将 d 的内容写入其中并再次关闭它。所以它只会包含d当时包含的内容,而且不涉及加密。
猜你喜欢
  • 1970-01-01
  • 2021-10-20
  • 2017-02-03
  • 2013-11-19
  • 2019-03-04
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多