Я использую простой CipherInput/OutputStream, чтобы попытаться зашифровать/дешифровать файлы в android.CipherOutputStream corruptting headers в Android
Проблема, с которой я сталкиваюсь, состоит в том, что она, кажется, повреждает первые несколько байтов файла, но не все остальное. Вот пример вывода из простого текстового файла:
Оригинальный текст:
"Test for Android cipher. The quick brown fox jumps over the lazy dog."
задействованного через шифрование и дешифрование:
@ÍØJb¢çc°ÌHOšpher. The quick brown fox jumps over the the lazy dog.
Вот мой код:
public static SecretKey generateKey(Context c, char[] passphraseOrPin) throws NoSuchAlgorithmException, InvalidKeySpecException {
// Number of PBKDF2 hardening rounds to use. Larger values increase
// computation time. You should select a value that causes computation
// to take >100ms.
byte[] salt = Settings.Secure.getString(c.getContentResolver(),
Settings.Secure.ANDROID_ID).getBytes();
final int iterations = 1000;
final int outputKeyLength = 128;
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
Log.d("HIDEMYPICS","Secret Key: " + toHex(secretKey.getEncoded()));
return secretKey;
}
public static boolean decryptFileFromUri(Context context, Uri file, String keyphrase) {
try {
File f = new File(getRealPathFromURI(context, file));
FileInputStream fis = new FileInputStream(f);
File ef = new File(f.toString().replace(".epf", ""));
FileOutputStream fos = new FileOutputStream(ef);
Log.d("HIDEMYPICS","Decrypting: " + f.toString());
SecretKey key = generateKey(context, keyphrase.toCharArray());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
Log.d("HIDEMYPICS","Decrypted to: " + ef.toString());
return true;
} catch (IOException e){
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return false;
}
public static boolean encryptFileFromUri(Context context, Uri file, String keyphrase) {
try {
File f = new File(getRealPathFromURI(context, file));
FileInputStream fis = new FileInputStream(f);
File ef = new File(f.toString() + ".epf");
FileOutputStream fos = new FileOutputStream(ef);
Log.d("HIDEMYPICS","Encrypting: " + f.toString());
SecretKey key = generateKey(context, keyphrase.toCharArray());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
Log.d("HIDEMYPICS","Encrypted to: " + ef.toString());
return true;
} catch (IOException e){
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return false;
}
ОБНОВЛЕНИЕ:
посоветовали явно добавить случайный IV к шифру установке и добавлены/изменены следующим строкам коды, чтобы облегчить его:
SecureRandom r = new SecureRandom();
byte[] ivBytes = new byte[16];
r.nextBytes(ivBytes);
SecretKey key = generateKey(context, keyphrase.toCharArray());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivBytes));
Законченных с тем же результатом. Первые несколько байтов текстового файла все еще были повреждены.
ОКОНЧАТЕЛЬНЫЙ ОТВЕТ:
Не уверен, что я сделал, но на предложения ниже я попытался статический IV и он все еще проявлял такое же поведение, но я переместил заявление и что-то случилось; вероятно, где-то была опечатка. Теперь проблема решена, и вот окончательный рабочий код. Спасибо всем, что помогло!
private static final byte[] ivBytes = {109,15,57,79,75,112,50,91,18,18,107,127,65,68,12,69};
public static SecretKey generateKey(Context c, char[] passphraseOrPin) throws NoSuchAlgorithmException, InvalidKeySpecException {
// Number of PBKDF2 hardening rounds to use. Larger values increase
// computation time. You should select a value that causes computation
// to take >100ms.
byte[] salt = Settings.Secure.getString(c.getContentResolver(),
Settings.Secure.ANDROID_ID).getBytes();
final int iterations = 1000;
final int outputKeyLength = 128;
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
return secretKey;
}
public static boolean decryptFileFromUri(Context context, Uri file, String keyphrase) {
try {
File f = new File(getRealPathFromURI(context, file));
FileInputStream fis = new FileInputStream(f);
File ef = new File(f.toString().replace(".epf", ""));
FileOutputStream fos = new FileOutputStream(ef);
SecretKey key = generateKey(context, keyphrase.toCharArray());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivBytes));
// Wrap the output stream
CipherInputStream cis = new CipherInputStream(fis, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
fos.flush();
}
// Flush and close streams.
fos.close();
cis.close();
f.delete();
return true;
} catch (IOException e){
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return false;
}
public static boolean encryptFileFromUri(Context context, Uri file, String keyphrase) {
try {
File f = new File(getRealPathFromURI(context, file));
FileInputStream fis = new FileInputStream(f);
File ef = new File(f.toString() + ".epf");
FileOutputStream fos = new FileOutputStream(ef);
SecretKey key = generateKey(context, keyphrase.toCharArray());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivBytes));
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
cos.flush();
}
// Flush and close streams.
cos.close();
fis.close();
f.delete();
return true;
} catch (IOException e){
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return false;
}
Пробовал это и, к сожалению, не работал: /. Тот же результат. Первые несколько байтов файла повреждены. Добавлено обновление, касающееся этого. – Nuvious
Это одно предложение с примерно 11 словами, и вам все еще удается прочитать только его первую часть. Во время шифрования и дешифровки значение IV должно совпадать. –
Я попытаюсь получить пример шифрованного текста, но он шифрует весь фронт сообщения назад; то, что вы видите, - это расшифрованное сообщение. Я также попытался использовать статический 128-битный IV-титр выше описанной случайной установки и до сих пор не радость. – Nuvious