Подтвердить что ты не робот

Как зашифровать и дешифровать файл в Android?

Я хочу зашифровать файл и сохранить его на SD-карте. Я хочу расшифровать этот зашифрованный файл и снова сохранить его на SD-карте. Я попытался зашифровать файл, открыв его как поток файлов и зашифровав, но он не работает. Мне нужна идея о том, как это сделать.

4b9b3361

Ответ 1

Используйте CipherOutputStream или CipherInputStream с Cipher и вашим FileInputStream/FileOutputStream.

Я бы предложил что-то вроде Cipher.getInstance("AES/CBC/PKCS5Padding") для создания класса Cipher. Режим CBC безопасен и не имеет уязвимостей режима ECB для неслучайных открытых текстов. Он должен присутствовать в любой универсальной криптографической библиотеке, обеспечивая высокую совместимость.

Не забудьте использовать вектор инициализации (IV), сгенерированный безопасным генератором случайных чисел, если вы хотите зашифровать несколько файлов одним и тем же ключом. Вы можете добавить префикс IV в начале зашифрованного текста. Это всегда ровно один блок (16 байт).

Если вы хотите использовать пароль, убедитесь, что вы используете хороший механизм получения ключей (посмотрите шифрование на основе пароля или получение ключа на основе пароля). PBKDF2 - наиболее часто используемая схема получения ключей на основе пароля, и она присутствует в большинстве сред выполнения Java, включая Android. Обратите внимание, что SHA-1 является немного устаревшей хеш-функцией, но она должна быть в порядке в PBKDF2 и в настоящее время предоставляет наиболее совместимую опцию.

Всегда указывайте кодировку символов при кодировании/декодировании строк, иначе у вас возникнут проблемы, если кодировка платформы отличается от предыдущей. Другими словами, не используйте String.getBytes(), но используйте String.getBytes(StandardCharsets.UTF_8).

Чтобы сделать его более безопасным, добавьте криптографическую целостность и подлинность, добавив безопасную контрольную сумму (MAC или HMAC) поверх зашифрованного текста и IV, предпочтительно с использованием другого ключа. Без тега аутентификации зашифрованный текст может быть изменен таким образом, что изменение не может быть обнаружено.

Имейте в виду, что CipherInputStream может не сообщать BadPaddingException, это включает в себя BadPaddingException, созданный для аутентифицированных шифров, таких как GCM. Это сделало бы потоки несовместимыми и небезопасными для таких аутентифицированных шифров.

Ответ 2

У меня была похожая проблема, и для шифрования/дешифрования я придумал это решение:

public static byte[] generateKey(String password) throws Exception
{
    byte[] keyStart = password.getBytes("UTF-8");

    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
    sr.setSeed(keyStart);
    kgen.init(128, sr);
    SecretKey skey = kgen.generateKey();
    return skey.getEncoded();
}

public static byte[] encodeFile(byte[] key, byte[] fileData) throws Exception
{

    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(fileData);

    return encrypted;
}

public static byte[] decodeFile(byte[] key, byte[] fileData) throws Exception
{
    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);

    byte[] decrypted = cipher.doFinal(fileData);

    return decrypted;
}

Чтобы сохранить зашифрованный файл в sd do:

File file = new File(Environment.getExternalStorageDirectory() + File.separator + "your_folder_on_sd", "file_name");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] yourKey = generateKey("password");
byte[] filesBytes = encodeFile(yourKey, yourByteArrayContainigDataToEncrypt);
bos.write(fileBytes);
bos.flush();
bos.close();

Для декодирования файла используйте:

byte[] yourKey = generateKey("password");
byte[] decodedData = decodeFile(yourKey, bytesOfYourFile);

Для чтения из файла в байтовый массив существует другой выход. Пример: http://examples.javacodegeeks.com/core-java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/

Ответ 3

Вы можете использовать java-aes-crypto или Facebook Conceal

Java-АЕС-криптографические

Цитирование из репо

Простой класс Android для шифрования и расшифровывать строки, стремясь избегайте классических ошибок, от которых страдает большинство таких классов.

Facebook скрыть

Цитирование из репо

Conceal предоставляет простые API для Android для быстрого шифрования и аутентификация данных

Ответ 4

Используйте CipherOutputStream или CipherInputStream с помощью Cipher и вашего FileOutputStream/FileInputStream.

Ответ 5

У нас есть одна и та же проблема, и ее решает кто-то в моей теме. Вы должны просто взглянуть на: CipherInputStream и CipherOutputStream. Они используются для шифрования и дешифрования потоков байтов. для подробного исходного кода ознакомьтесь с Кириллом по этой ссылке: Как зашифровать файл с SD-карты с помощью AES на Android?

Ответ 6

У меня была та же проблема, я получил решение из этого кода.

private static final String ALGO = "AES";
private static final byte[] keyValue = new byte[] { 'o', 'n', 'e', 'n','e', 't', 'e','d', 'o', 'c', 'e', 'i', 'r', 's', 'r', 'p' };
    public static String decrypt(String encryptedData){
        String decryptedValue = null;
        try{
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        decryptedValue = new String(decValue);
    }catch(Exception e){
        //LOGGER.error("In TD:" + e);
        //Teneno_StartupService.loadForConnectionFailed();
    }
    return decryptedValue;
}
private static Key generateKey(){
    Key key = new SecretKeySpec(keyValue, ALGO);
    return key;
}