如何为Android Kitkat及更高版本加密和解密文件?

时间:2017-09-12 07:43:32

标签: android encryption

我谷歌搜索和测试解决方案一段时间,到目前为止没有成功。它总是存在一些问题。以下代码是"工作" (在Android Kitkat及更高版本中,意味着在运行时不显示任何错误),但解密文件不可读。为什么呢?

final static byte[] iv = new byte[16];//ADDED
final static int buffer = 102400;
final static String encryptionType = "AES/CFB8/NoPadding";//CHANGED TO DIFFERENT TYPE

static void encrypt(String password, File fileInput, File fileOutput) throws Exception {

    IvParameterSpec ivParams = new IvParameterSpec(iv);//ADDED

    FileInputStream fis = new FileInputStream(fileInput);
    FileOutputStream fos = new FileOutputStream(fileOutput);

    SecretKeySpec sks = new SecretKeySpec(password.getBytes("UTF-8"), encryptionType);

    Cipher cipher = Cipher.getInstance(encryptionType);
    //cipher.init(Cipher.ENCRYPT_MODE, sks);REPLACED
    cipher.init(Cipher.ENCRYPT_MODE, sks, ivParams);
    CipherOutputStream cos = new CipherOutputStream(fos, cipher);

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

    cos.flush();
    cos.close();
    fis.close();
}

static void decrypt(String password, File fileInput, File fileOutput) throws Exception {

    IvParameterSpec ivParams = new IvParameterSpec(iv);//ADDED

    FileInputStream fis = new FileInputStream(fileInput);
    FileOutputStream fos = new FileOutputStream(fileOutput);

    SecretKeySpec sks = new SecretKeySpec(password.getBytes("UTF-8"), encryptionType);

    Cipher cipher = Cipher.getInstance(encryptionType);
    //cipher.init(Cipher.ENCRYPT_MODE, sks);REPLACED
    cipher.init(Cipher.DECRYPT_MODE, sks, ivParams);
    CipherInputStream cis = new CipherInputStream(fis, cipher);

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

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

编辑:在我将类型更改为" AES / CFB8 / NoPadding"后,似乎没问题,过程中没有错误,但解密文件无法读取。

2 个答案:

答案 0 :(得分:1)

解密方法中的问题是由以下行引起的:

cipher.init(Cipher.ENCRYPT_MODE, sks);

模式需要Cipher.DECRYPT_MODE,因此该行应为

cipher.init(Cipher.DECRYPT_MODE, sks);

其他问题是长期过时的DESede算法的使用,缺乏任何IV生成和处理,没有良好的基于​​密码的密钥派生算法,以及密文上缺少任何MAC。正确使用AES GCM模式以及正确的随机数生成和处理,以及使用PBKDF2(可在Android和Oracle Java上使用)将代表重大改进。

您没有提供IV,因此会自动生成一个IV。您必须找到将此IV传输给收件人的方法。通常,IV / Nonce前置于密文并由接收者剥离以便解密数据。 CipherInputStream / CipherOutputStream不会为您执行此操作,因此您必须自己执行此操作。

答案 1 :(得分:0)

我终于通过使用更短的密码解决了这个问题。我不知道为什么,但在Android 7和8上,长密码没有问题,但Android 4.4上的相同密码会导致疯狂的错误和制动加密。