【问题标题】:How to encrypt and decrypt file for Android Kitkat and higher?如何为 Android Kitkat 及更高版本加密和解密文件?
【发布时间】:2023-03-04 17:39:01
【问题描述】:

我正在谷歌搜索和测试解决方案一段时间,但到目前为止没有成功。它总是有一些问题。以下代码在 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”后,似乎没问题,处理过程中没有错误,但解密后的文件不可读。

【问题讨论】:

标签: android encryption


【解决方案1】:

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

cipher.init(Cipher.ENCRYPT_MODE, sks);

模式需要Cipher.DECRYPT_MODE,所以该行应该是

cipher.init(Cipher.DECRYPT_MODE, sks);

其他问题包括使用过时已久的 DESede 算法、缺乏任何 IV 生成和处理、缺乏良好的基于​​密码的密钥派生算法以及密文上缺乏任何 MAC。正确使用 AES GCM 模式以及正确的 nonce 生成和处理,以及使用 PBKDF2(在 Android 和 Oracle Java 上可用)将代表显着的改进。

您不提供 IV,因此会自动为您生成一个。您必须找到一种方法将此 IV 传输给接收者。通常 IV/Nonce 在密文之前并被接收者剥离以解密数据。 CipherInputStream/CipherOutputStream 不会为你做这件事,所以你必须自己做。

【讨论】:

  • 我添加了 IV,但仍然是同样的错误。我在这里更新了代码。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2018-03-31
    • 2016-10-15
    • 2011-05-15
    • 1970-01-01
    • 2019-03-31
    • 2011-07-08
    • 2012-01-01
    • 1970-01-01
    相关资源
    最近更新 更多