Ответ 1
Что нужно знать в общем:
- Ключ! = Пароль
-
SecretKeySpec
ожидает ключ, а не пароль. Увидеть ниже
-
- Это может быть связано с ограничением политики, которое не позволяет использовать 32-байтовые ключи. Смотрите другой ответ на этот вопрос
В твоем случае
Проблема № 1: вы передаете пароль вместо ключа.
AES поддерживает только размеры ключей 16, 24 или 32 байта. Вам нужно либо указать именно эту сумму, либо вы получаете ключ от того, что вы вводите.
Существуют разные способы получения ключа из ключевой фразы. Java предоставляет реализацию PBKDF2 для этой цели.
Я использовал ответ erickson, чтобы нарисовать полную картину (только шифрование, поскольку расшифровка похожа, но включает разделение зашифрованного текста):
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 65536, 256); // AES-256
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] key = f.generateSecret(spec).getEncoded();
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
byte[] ivBytes = new byte[16];
random.nextBytes(ivBytes);
IvParameterSpec iv = new IvParameterSpec(ivBytes);
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, keySpec, iv);
byte[] encValue = c.doFinal(valueToEnc.getBytes());
byte[] finalCiphertext = new byte[encValue.length+2*16];
System.arraycopy(ivBytes, 0, finalCiphertext, 0, 16);
System.arraycopy(salt, 0, finalCiphertext, 16, 16);
System.arraycopy(encValue, 0, finalCiphertext, 32, encValue.length);
return finalCiphertext;
Другие вещи, которые нужно иметь в виду:
- Всегда используйте полное имя шифра.
AES
не подходит в таком случае, потому что разные поставщики JVM/JCE могут использовать разные значения по умолчанию для режима работы и заполнения. ИспользуйтеAES/CBC/PKCS5Padding
. Не используйте режим ECB, потому что он не является семантически безопасным. - Если вы не используете режим ECB, вам нужно отправить IV вместе с зашифрованным текстом. Обычно это делается путем добавления префикса IV к массиву байтов зашифрованного текста. IV автоматически создается для вас, и вы можете получить его через
cipherInstance.getIV()
. - Всякий раз, когда вы отправляете что-то, вы должны быть уверены, что это не было изменено по пути. Трудно правильно реализовать шифрование с помощью MAC. Я рекомендую вам использовать режим аутентификации, такой как CCM или GCM.