Статья первоначально опубликована на моем личном сайте в разделе Как безопасно хранить пароль с помощью соли и перца
В предыдущей статье я писал как безопасно хранить пароль в базе данных . Статья привлекла внимание многих коллег-разработчиков, и поэтому я решил улучшить ее еще больше, написав эту статью. Видите ли, несмотря на то, что хранить пароль в виде соленого хэша очень безопасно, существует дополнительный уровень безопасности, который можно добавить, чтобы сделать вещи еще более трудными для взлома: перец.
Часть “перец” предназначена не для замены соленого хэша, а для дальнейшего улучшения алгоритма, чтобы данные хранились более безопасным способом и практически исключали возможность использования любых просочившихся данных.
Как добавить перец в ваш соленый окрошку
“Перец” на самом деле является слоем шифрования поверх полученного хэша. Алгоритм следующий: вы хэшируете пароль, как и раньше. Полученный хэш затем шифруется с использованием алгоритма шифрования с симметричным ключом. Полученные зашифрованные данные – это те, которые фактически хранятся в базе данных.
Когда вы хотите проверить введенный пользователем пароль, вы повторяете алгоритм и сравниваете результат с сохраненным зашифрованным хэшем. Если они совпадают, значит, введенный пароль правильный. Преимущество заключается в том, что даже хэш не является открытым, и вам не нужно расшифровывать его при проверке отправленного пароля, так как для одних и тех же входных данных будут возвращены одни и те же значения.
Однако следует иметь в виду, что пароль, используемый для шифрования, не должен храниться в базе данных. Это очень важно, так как любой дамп базы данных или разоблачение также приведет к утечке пароля, и будет легко просто расшифровать все хэши. Это все равно будет только один слой повержен, но с “перцем” мы хотим избежать даже этого.
Внедрение “перца” для хэша вашего пароля
Во-первых, вам нужно будет определить перец. Опять же, не храните его в одной и той же базе данных. Вы можете использовать файлы конфигурации, внешнюю, но защищенную систему (например, хранилище Hashicorp или HSM). Следует иметь в виду одну вещь: перец следует поворачивать, поэтому всегда назначайте ему версию.
В таблице, где вы храните хэшированный пароль и соль, также храните версию pepper. Это делается для того, чтобы вы знали, какой секрет использовать при расшифровке пароля, предоставленного пользователем и чтобы вы могли аннулировать пароль, ЕСЛИ пароль будет скомпрометирован. Столбец может быть простым INT().
Теперь перейдем к части java.
char[] pepper = readPepper(); String salt = CryptoUtils.generateSalt(); String passwordHash = CryptoUtils.generateHashForPassword(newUserDTO.getPassword(), salt, pepper));
Важные вещи происходят внутри метода генерации хэша для пароля(). Упрощенную версию можно прочитать ниже. Это модифицированная версия той, что была в оригинальной статье, но AES использовалась для шифрования первоначально сгенерированного хэша.
public static String generateHashForPassword(String password, String salt, String pepper) throws NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, InvalidKeyException {
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
byte[] hash = secretKeyFactory.generateSecret(spec).getEncoded();
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKey key = new SecretKeySpec(pepper.getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = cipher.doFinal(hash);
return Base64.getEncoder()
.encodeToString(cipherText);
}
Чтобы подтвердить, что пароль, введенный пользователем при входе в систему, совпадает с паролем, предоставленным при регистрации, вы повторяете весь алгоритм. Если сохраненная строка Base64 совпадает с вычисленной, пароли будут одинаковыми. Вообще нет необходимости расшифровывать сохраненные данные. Единственное, что следует иметь в виду, это то, что используется один и тот же перец, что можно сделать, прочитав сохраненную версию перца.
Выводы
Дальнейшее повышение безопасности сохраненных паролей не так уж сложно. Действительно, это увеличивает время обработки, но ненамного. Это небольшой компромисс, если вы думаете о дополнительных преимуществах. Просто храните перец в безопасности, и если он будет раскрыт, поверните его и заново зашифруйте все.
Статья первоначально опубликована на моем личном сайте в разделе Как безопасно хранить пароль с помощью соли и перца
Оригинал: “https://dev.to/pazvanti/using-pepper-to-increase-password-storing-security-83f”