Каков надлежащий способ выполнения аутентифицированного шифрования в Java?

Аутентифицированное шифрование требует, чтобы мы использовали принятый стандарт для шифрования и аутентификации сообщения. Таким образом, мы оба шифруем сообщение и вычисляем MAC-адрес сообщения, чтобы убедиться, что он не был изменен.

Этот вопрос описывает способ усиления и шифрования ключей на основе пароля:

/* Derive the key, given password and salt. */
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
/* Encrypt the message. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] ciphertext = cipher.doFinal("Hello, World!".getBytes("UTF-8"));

Но насколько я могу судить, это не вычисляет какой-либо MAC на зашифрованном тексте и поэтому будет небезопасным. Каков приемлемый стандарт для выполнения аутентифицированного шифрования в Java?

Ответ 1

Я бы рекомендовал использовать шифрование в режиме GCM. По умолчанию он включен в последнюю версию JDK (1.7). Он использует шифрование в режиме счетчика (шифр потока, без заполнения) и добавляет тег аутентификации. Одно большое преимущество заключается в том, что для этого требуется только один ключ, тогда как HMAC добавляет еще один ключ в микс. У Bouncy Castle также есть реализация, которая совместима с одним, предоставленным Oracle.

Шифрование режима GCM также относится к TLS RFC и в XML-шифровании 1.1 (оба не являются окончательными). Режим GCM предоставляет все три функции безопасности: конфиденциальность, целостность и достоверность отправки данных. Строка будет "AES/GCM/NoPadding" вместо CBC, которую вы сейчас развертываете. Как сказано, убедитесь, что у вас есть последний JDK от Oracle или у вас установлен провайдер Bouncy Castle.

Также ознакомьтесь с моим ответом здесь, который в основном связан с кодировкой String, но я также успешно выполнил режим GCM - см. комментарий.

Ответ 2

При передаче файлов с одного сервера на другой с помощью защищенного ftp я использую пары private/public key с закрытым ключом, находящимся на сервере "from", и открытым ключом, находящимся на сервере "to".

Использование пар private/public key является безопасным стандартом при передаче файлов.

Я считаю, что это также было бы безопасным средством в контексте приложения Java.

Отъезд Генерация и проверка подписей и Генерировать публичные и частные Ключи для более подробной информации об использовании настройки пары частных/открытых ключей для цифровых подписей в Java.