【问题标题】:AES Algorithm for audio files in AndroidAndroid中音频文件的AES算法
【发布时间】:2015-02-16 05:51:23
【问题描述】:

您好,我正在我的项目中进行 AES 加密和解密。

我有一个使用“AES/CBC/pkcs5padding”加密的 .mp4 文件。

我有用于加密音频文件前 256 个字节的密钥和 iv 值。

我需要使用相同的算法、密钥和 iv 值解密文件的前 256 个字节。

我关注了一些链接 (link1,link2)。

我有一个音频播放器演示,并尝试将我的部分(AES 加密和解密)实现为演示。

下面我解释了我所做的代码。

此方法从 res/raw 文件夹下的加密文件中读取数据。

private void readFile() throws IOException, InvalidKeyException,
        NoSuchAlgorithmException, NoSuchPaddingException,
        InvalidAlgorithmParameterException, IllegalBlockSizeException,
        BadPaddingException {

    Context context = getApplicationContext();
    /*
     * InputStream is = getResources().openRawResource(
     * getResources().getIdentifier("raw/encrypted", "raw",
     * getPackageName())); String text = "";
     * 
     * int size = is.available(); byte[] buffer = new byte[size];
     * is.read(buffer);
     */

    InputStream inStream = context.getResources().openRawResource(
            R.raw.encrypted);

    // get string from file

    byte[] music = new byte[256];
    for (int i = 0; i <= inStream.available(); i = i + 255) {
        music = convertStreamToByteArray(inStream, i);
        byte[] bytesToWrite = new byte[256];

        bytesToWrite = music;
        if (i == 0) {
            bytesToWrite = AES256Cipher.decrypt(iv.getBytes("UTF-8"),
                    key.getBytes("UTF-8"), music);
            // writeFirstSetOfBytes("decrypted.mp4");
        }

        writeFirstSetOfBytes(bytesToWrite);

    }
}

解密方法来自link1。这里我传递了上面提到的key和iv值。

public static byte[] decrypt(byte[] ivBytes, byte[] keyBytes,
            byte[] textBytes) throws java.io.UnsupportedEncodingException,
            NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, InvalidAlgorithmParameterException,
            IllegalBlockSizeException, BadPaddingException {

        AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        // SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE,
                new SecretKeySpec(keyBytes, "AES"), ivSpec);
        return cipher.doFinal(textBytes);
    }

此方法用于从输入流中获取字节数组。

public static byte[] convertStreamToByteArray(InputStream is, int size)
        throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buff = new byte[256];
    int i = Integer.MAX_VALUE;
    while ((i = is.read(buff, size, buff.length)) > 0) {
        baos.write(buff, 0, i);
    }

    return baos.toByteArray(); // be sure to close InputStream in calling
                                // function
}

此方法将接收到的字节数组写入目标文件(decrypted.mp4)

private void writeFirstSetOfBytes(byte[] byteToWrite) {

    File file = new File(
            Environment
                    .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
            "/decrypted.mp4");
    FileOutputStream stream = null;
    if (!file.exists()) {
        try {
            file.createNewFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    // writing data into file
    try {
        stream = new FileOutputStream(file);

        stream.write(byteToWrite);
        stream.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

我收到以下错误。

javax.crypto.IllegalBlockSizeException: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length

我怎样才能达到我的要求?

  1. 如何只解密前 256 个字节的数据?
  2. 是否有任何代码行为错误?
  3. 是否有可用的第三方库?

如果需要更多说明,请告诉我。

【问题讨论】:

  • 只是一个旁注。 decrypt() 例程需要 ivkey 作为原始字节,但您的 readFile() 例程似乎将它们从某些文本表示形式转换。你确定你没有传递十六进制字符串而不是原始字节吗?
  • 我真的不知道从哪里开始。您的流处理完全不正确 - 包括两个循环,您使用的是 i = i + 255,CBC 模式可能不是一个好主意。

标签: android cryptography aes


【解决方案1】:

根据 Wikipedia,PKCS#5 是 PKCS#7 的特殊变体,专门为 64 位块定义(而 PKCS#7 适用于任何块大小),但 AES 仅使用 128 位块(或更大,但这不包括在标准中),因此不匹配。尝试其他填充方案。

【讨论】:

  • 呃,不。请参阅我的回答 here,包括 Java 细节。
  • @owlstead 信不信由你,但你对 Crypto 的回答正是我得出结论的来源之一。 :-) 特别是:“PKCS#5 padding can not be used for AES”这一行。库实际上不应区分 PKCS#5 和 PKCS#7 的规则只是一项正式规定——除非明确验证,否则无法确定特定库的特定版本是否遵守此规则,而这正是我推荐的把检查放在首位,这样检查就变得微不足道了。无论如何,纠正不正确的标识符是个好主意。
  • 我当然很荣幸成为您的答案的来源,但是“一些加密库(例如 Java 中的 SUN 提供程序)指示 PKCS#5 应该使用 PKCS#7 - “PKSC5Padding”应该一直是“PKCS7Padding”。”也是该答案的一部分。换句话说,如果您指定 PKCS#5,那么实际上会使用 PKCS#7 填充。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-30
  • 1970-01-01
  • 2011-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-15
相关资源
最近更新 更多