简体   繁体   English

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

[英]How to encrypt and decrypt file for Android Kitkat and higher?

I am googling and testing solution for a while and so far no success. 我正在搜索和测试解决方案一段时间,到目前为止没有成功。 There is always some problem with it. 总是有一些问题。 Following code is "working" (meaning do not show any error while it is running) on Android Kitkat and higher, but decrypted files are not readable. 以下代码在Android Kitkat和更高版本上是“有效的”(意味着在运行时不显示任何错误),但解密的文件不可读。 Why? 为什么?

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();
}

EDIT: After I changed type to "AES/CFB8/NoPadding", it seems to be ok, there is no error in process, but decrypted file is not readable. 编辑:我将类型更改为“ AES / CFB8 / NoPadding”后,似乎没问题,进程中没有错误,但是解密后的文件不可读。

The problem in the decrypt method is caused by this line: 解密方法中的问题是由以下行引起的:

cipher.init(Cipher.ENCRYPT_MODE, sks);

the mode needs to Cipher.DECRYPT_MODE , so the line should be 该模式需要Cipher.DECRYPT_MODE ,因此该行应为

cipher.init(Cipher.DECRYPT_MODE, sks);

Other issues are the use of the long obsolete DESede algorithm, the lack of any IV generation and handling, the absence of a good password-based key derivation algorithm, and the lack of any MAC on the ciphertext. 其他问题包括使用过长的DESede算法,缺少任何IV生成和处理,缺少基于密码的良好密钥派生算法以及密文上没有任何MAC。 Correctly using AES GCM mode with proper nonce generation and handling, and use of PBKDF2 (which is available on Android and Oracle Java) would represent significant improvements. 正确使用具有适当的随机数生成和处理的AES GCM模式,以及使用PBKDF2(可在Android和Oracle Java上使用)将代表重大改进。

You don't supply an IV, so one is generated for you automatically. 您没有提供IV,因此会自动为您生成一个。 You must find a way to transmit this IV to the recipient. 您必须找到一种方法将此IV传送给收件人。 Typically the IV/Nonce is prepending to the ciphertext and stripped off by the recipient in order to decrypt the data. 通常,IV / Nonce在密文之前,并被接收者剥离以解密数据。 CipherInputStream/CipherOutputStream does not do this for you, so you must do it on your own. CipherInputStream / CipherOutputStream不会为您执行此操作,因此您必须自己执行此操作。

I finally solve this problem by using shorter password. 我终于通过使用较短的密码解决了这个问题。 I am not sure why, but on Android 7 and 8, there is no problem with long password, but same password on Android 4.4 leads to crazy errors and brake encryption. 我不确定为什么,但是在Android 7和8上,长密码没有问题,但是在Android 4.4上使用相同的密码会导致疯狂的错误和制动加密。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM