2016-01-20 270 views
0

我需要下载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; 
} 
+0

最新错误? – petey

+0

@petey问题是由解密生成的mp3文件不起作用。 不要陷入异常,不要在加密和解密时崩溃。简单解密会生成MediaPlayer无法读取的文件。加密之前的mp3文件有效,但是mp3解密不是 –

回答

0

你似乎有在任何你加密一个错字或解密的方法。

在加密:

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是约10X比加密字节数组大。

+0

虽然这有些奇怪,但它怎么会导致上述问题呢? – Henry

+0

如果文件末尾有72K个未初始化的字节,可能会导致它无法读取。不是mp3的专家,但似乎有可能。 – PunDefeated

+0

@PunDefeated忽略8之后的0,真的是8192.这个80192是最后一次尝试增加字节 –

0

这样做后:

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文件将只包含最后一个缓冲区满的数据。此外,这些数据不会被加密。

+0

解释得更好。我不明白 –

+0

在最后3行中,你打开一个新的流,写入'd'的内容并再次关闭它。所以它只包含当时包含的“d”,此外,不涉及加密。 – Henry