Что не так в следующем примере?
Проблема в том, что первая часть расшифрованной строки - ерунда. Впрочем, в остальном все нормально, я получаю ...
Result: `£eB6O�geS��i are you? Have a nice day.
@Test
public void testEncrypt() {
try {
String s = "Hello there. How are you? Have a nice day.";
// Generate key
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
SecretKey aesKey = kgen.generateKey();
// Encrypt cipher
Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);
// Encrypt
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);
cipherOutputStream.write(s.getBytes());
cipherOutputStream.flush();
cipherOutputStream.close();
byte[] encryptedBytes = outputStream.toByteArray();
// Decrypt cipher
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);
// Decrypt
outputStream = new ByteArrayOutputStream();
ByteArrayInputStream inStream = new ByteArrayInputStream(encryptedBytes);
CipherInputStream cipherInputStream = new CipherInputStream(inStream, decryptCipher);
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = cipherInputStream.read(buf)) >= 0) {
outputStream.write(buf, 0, bytesRead);
}
System.out.println("Result: " + new String(outputStream.toByteArray()));
}
catch (Exception ex) {
ex.printStackTrace();
}
}
java
encryption
aes
TedTrippin
источник
источник
Ответы:
Многие люди, в том числе и я, сталкиваются с множеством проблем при выполнении этой работы из-за отсутствия некоторой информации, например, забвения преобразовать в Base64, векторов инициализации, набора символов и т. Д. Поэтому я подумал о создании полностью функционального кода.
Надеюсь, это будет полезно для всех вас: для компиляции вам понадобится дополнительная банка кодеков Apache Commons, которая доступна здесь: http://commons.apache.org/proper/commons-codec/download_codec.cgi
источник
System.out.println("encrypted string:" + DatatypeConverter.printBase64Binary(encrypted));
byte[] original = cipher.doFinal(DatatypeConverter.parseBase64Binary(encrypted));
SecureRandom
Здесь решение без
Apache Commons Codec
«SBase64
:Пример использования:
Печать:
источник
encrypt(String)
а нетencrypt(byte[] )
? Шифрование (в том числе и дешифрование) - это процесс, основанный на байтах (в любом случае AES). Шифрование принимает байты на входе и выводит байты, так же как и дешифрование (пример:Cipher
объект делает). Теперь одним из конкретных вариантов использования может быть зашифрованные байты, поступающие из String или отправляемые как String (вложение MIME base64 для Mail ...), но это проблема кодирования байтов, для которых существуют сотни решения, совершенно не связанные с AES / шифрованием.Strings
поскольку в основном я работаю с ним 95% времени, и вы все равно конвертируете.Мне кажется, что вы неправильно работаете со своим вектором инициализации (IV). Прошло много времени с тех пор, как я в последний раз читал об AES, IV и цепочке блоков, но ваша строка
вроде не в порядке. В случае AES вы можете думать о векторе инициализации как о «начальном состоянии» экземпляра шифра, и это состояние представляет собой часть информации, которую вы не можете получить от своего ключа, а от фактического вычисления шифра шифрования. (Можно было бы возразить, что, если бы IV можно было извлечь из ключа, это было бы бесполезно, поскольку ключ уже передан экземпляру шифра во время его фазы инициализации).
Следовательно, вы должны получить IV в виде байта [] из экземпляра шифра в конце вашего шифрования.
и вы должны инициализировать свой
Cipher
inDECRYPT_MODE
этим байтом []:Тогда ваша расшифровка должна быть в порядке. Надеюсь это поможет.
источник
IV, который вы используете для дешифрования, неверен. Замените этот код
С этим кодом
И это должно решить вашу проблему.
Ниже приведен пример простого класса AES в Java. Я не рекомендую использовать этот класс в производственной среде, поскольку он может не учитывать все специфические потребности вашего приложения.
Обратите внимание, что AES не имеет ничего общего с кодированием, поэтому я решил обрабатывать его отдельно и без каких-либо сторонних библиотек.
источник
"/NoPadding"
. CTR - это режим, который превращает AES в потоковый шифр, а потоковый шифр работает с байтами, а не с блоками.В этом ответе я предпочитаю подходить к основной теме «Простой пример шифрования / дешифрования Java AES», а не к конкретному вопросу отладки, потому что я думаю, что это принесет пользу большинству читателей.
Это краткое изложение моего сообщения в блоге о шифровании AES в Java, поэтому я рекомендую прочитать его, прежде чем что-либо реализовывать. Тем не менее, я все же приведу простой пример для использования и дам несколько указателей, на что следует обращать внимание.
В этом примере я выберу использовать аутентификацию шифрование с Галуа Mode / счетчика или GCM режимом. Причина в том, что в большинстве случаев вам нужна целостность и аутентичность в сочетании с конфиденциальностью (подробнее читайте в блоге ).
Руководство по шифрованию / дешифрованию AES-GCM
Вот шаги, необходимые для шифрования / дешифрования с помощью AES-GCM с архитектурой криптографии Java (JCA) . Не смешивайте с другими примерами , так как тонкие различия могут сделать ваш код совершенно небезопасным.
1. Создать ключ
Поскольку это зависит от вашего варианта использования, я предполагаю самый простой случай: случайный секретный ключ.
Важный:
SecureRandom
2. Создайте вектор инициализации.
Вектор инициализации (IV) используется для того , что тот же самый секретный ключ будет создавать различные тексты шифров .
Важный:
SecureRandom
3. Зашифровать с помощью IV и ключа
Важный:
CipherInputStream
при шифровании больших блоков данныхcipher.updateAAD(associatedData);
Подробнее здесь.3. Сериализовать в одно сообщение
Просто добавьте IV и зашифрованный текст. Как было сказано выше, IV не обязательно должен быть секретным.
При необходимости закодируйте с помощью Base64, если вам нужно строковое представление. Используйте встроенную реализацию Android или Java 8 (не используйте кодек Apache Commons - это ужасная реализация). Кодирование используется для «преобразования» байтовых массивов в строковое представление, чтобы сделать его безопасным ASCII, например:
4. Подготовка к расшифровке: десериализация
Если вы закодировали сообщение, сначала декодируйте его в массив байтов:
Важный:
5. Расшифровать
Инициализируйте шифр и установите те же параметры, что и при шифровании:
Важный:
cipher.updateAAD(associatedData);
если вы добавили его во время шифрования.В этом суть можно найти рабочий фрагмент кода.
Обратите внимание, что самые последние реализации Android (SDK 21+) и Java (7+) должны иметь AES-GCM. В более старых версиях он может отсутствовать. Я по-прежнему выбираю этот режим, поскольку его проще реализовать, и он более эффективен по сравнению с аналогичным режимом Encrypt-then-Mac (например, с AES-CBC + HMAC ). См. Эту статью о том, как реализовать AES-CBC с HMAC .
источник
this is true for CBC mode but not for GCM
Вы имеете в виду всю часть или только это не обязательно должно быть непредсказуемым?Онлайн-редактор Рабочая версия: -
источник
Часто рекомендуется полагаться на решение, предоставляемое стандартной библиотекой:
Это напечатает «Текст для кодирования».
Решение основано на Справочном руководстве по архитектуре криптографии Java и ответе https://stackoverflow.com/a/20591539/146745 .
источник
Это улучшение по сравнению с принятым ответом.
Изменения:
(1) Использование случайного IV и добавление его к зашифрованному тексту
(2) Использование SHA-256 для генерации ключа из парольной фразы
(3) Нет зависимости от Apache Commons
источник
Другое решение с использованием java.util.Base64 с Spring Boot
Класс шифратора
Класс EncryptorController
application.properties
пример
HTTP: // локальный: 8082 / шифр / шифровать / jmendoza
2h41HH8Shzc4BRU3hVDOXA ==
HTTP: // локальный: 8082 / шифр / расшифровывать / 2h41HH8Shzc4BRU3hVDOXA ==
jmendoza
источник
Оптимизированная версия принятого ответа.
нет сторонних библиотек
включает IV в зашифрованное сообщение (может быть публичным)
пароль может быть любой длины
Код:
Использование:
Пример вывода:
источник
e.printStackTrace()
так называемого оптимизированного кода.