Я пытаюсь внедрить AES-шифрование на Android, в котором используется фраза для генерации SecretKey
. Я передаю то же самое byte[]
как вектор инициализации для шифров и как соль при создании SecretKey
с PBKDF2.Возможные ошибки в реализации AES в Android
Ключевая фраза предоставляется пользователем каждый раз, когда требуется шифрование/дешифрование.
На данный момент мне нужно только зашифровать одно значение в моей базе данных (если это имеет значение).
Вопросы:
- Я интересно, если с помощью того же
byte[]
как IV и соль ослабляет шифрование? - Есть ли причина переключиться с CBC на GCM, тогда функция GCM обеспечивает целостность данных?
- Я читал о том, что CBC подвержен атаке BEAST, использует новый случайный IV для каждого сообщения, как показано ниже, смягчает атаку BEAST?
Текущий исходный код:
public class AesEncryption {
private static final int KEY_SIZE = 16;
private static final int OUTPUT_KEY_LENGTH = 256;
private static final int ITERATIONS = 1000;
private String mPassphraseOrPin;
public AesEncryption(String passphraseOrPin) {
mPassphraseOrPin = passphraseOrPin;
}
public void encrypt(String id, String textToEncrypt) throws Exception {
byte[] iv = getIv();
SecretKey secretKey = generateKey(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));
byte[] cipherText = cipher.doFinal(textToEncrypt.getBytes("utf-8"));
byte[] ivCipherText = arrayConcat(iv, cipherText);
String encryptedText = Base64.encodeToString(ivCipherText, Base64.NO_WRAP);
storeEncryptedTextInDb(id, encryptedText);
}
public String decrypt(String id) throws Exception {
String encryptedText = getEncryptedTextFromDb(id);
byte[] ivCipherText = Base64.decode(encryptedText, Base64.NO_WRAP);
byte[] iv = Arrays.copyOfRange(ivCipherText, 0, KEY_SIZE);
byte[] cipherText = Arrays.copyOfRange(ivCipherText, KEY_SIZE, ivCipherText.length);
SecretKey secretKey = generateKey(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
String decrypted = new String(cipher.doFinal(cipherText), "utf-8");
return decrypted;
}
public SecretKey generateKey(byte[] salt) throws Exception {
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(mPassphraseOrPin.toCharArray(), salt, ITERATIONS, OUTPUT_KEY_LENGTH);
SecretKey tmp = secretKeyFactory.generateSecret(keySpec);
return new SecretKeySpec(tmp.getEncoded(), "AES");
}
private byte[] getIv() {
byte[] salt = new byte[KEY_SIZE];
new SecureRandom().nextBytes(salt);
return salt;
}
private byte[] arrayConcat(byte[] one, byte[] two) {
byte[] combined = new byte[one.length + two.length];
for (int i = 0; i < combined.length; ++i) {
combined[i] = i < one.length ? one[i] : two[i - one.length];
}
return combined;
}
}
Я предполагаю местную базу данных Android? –
@MaartenBodewes да. Я собираюсь сохранить зашифрованный текст в SharedPreferences. –
ОК, в этом случае нет никаких шансов на атаку в отношении данных, находящихся в пути (например, атаки CBC на оскорбление). К сожалению, я не могу выполнить полный обзор безопасности - ответ не тот. В целом, он окупается, чтобы посмотреть варианты защиты, предлагаемые самой платформой. –