У меня есть старое приложение на базе Symfony2, и я разрабатываю замену Dropwizard на Java. Я перенес все записи пользователя из старой БД в новую Datamodel. Я также добавил новые поля для паролей и импортировал старый пароль и солевые поля.Создание таких же хэшей, как symfony2, с помощью java (SHA-512)
Теперь я хочу сделать хорошо известную процедуру. Позвольте пользователю войти в систему, попробуйте новое поле пароля. Если это не удается, попробуйте перенесенные, если они работают, закодируйте пароль cleartext с новым алгоритмом и сохраните новый хеш в новом поле pasword. Чтобы пользователи переносили хэши паролей из старой процедуры в новую.
Звучит просто и нормально, это работает как обычно, но этот Symfony и PHP меня смущает.
Где я застрял, нужно создать тот же хэш с java, что и symfony. Старое приложение использует MessageDigestPasswordEncoder с "SHA512", кодирование base64 и 5000 итераций, все значения по умолчанию;)
Важными методами являются:
MessageDigestPasswordEncoder:
public function encodePassword($raw, $salt) {
if ($this->isPasswordTooLong($raw)) {
throw new BadCredentialsException('Invalid password.');
}
if (!in_array($this->algorithm, hash_algos(), true)) {
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
}
$salted = $this->mergePasswordAndSalt($raw, $salt);
$digest = hash($this->algorithm, $salted, true);
// "stretch" hash
for ($i = 1; $i < $this->iterations; ++$i) {
$digest = hash($this->algorithm, $digest.$salted, true);
}
return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
}
И BasePasswordEncoder:
protected function mergePasswordAndSalt($password, $salt) {
if (empty($salt)) {
return $password;
}
if (false !== strrpos($salt, '{') || false !== strrpos($salt, '}')) {
throw new \InvalidArgumentException('Cannot use { or } in salt.');
}
return $password.'{'.$salt.'}';
}
Это кажется прямым, но я придерживался его. Как я прочитал это делает:
- Объединить соли и пароль открытым текстом для: «пароль {соль}»
- Hash это строка с SHA-512 и возвращает двоичную строку в переваривать переменную
- итерацию 5k раза и использовать дайджест сцепляется с объединенном читаемых паролями перефразировать в дайджесте
- закодировать дайджест base64
Так вот моя попытка в Java:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public void legacyEncryption(String salt, String clearPassword) throws UnsupportedEncodingException, NoSuchAlgorithmException {
// Get digester instance for algorithm "SHA-512" using BounceCastle
MessageDigest digester = MessageDigest.getInstance("SHA-512", new BouncyCastleProvider());
// Create salted password string
String mergedPasswordAndSalt = clearPassword + "{" + salt + "}";
// First time hash the input string by using UTF-8 encoded bytes.
byte[] hash = digester.digest(mergedPasswordAndSalt.getBytes("UTF-8"));
// Loop 5k times
for (int i = 0; i < 5000; i++) {
// Concatenate the hash bytes with the clearPassword bytes and rehash
hash = digester.digest(ArrayUtils.addAll(hash, mergedPasswordAndSalt.getBytes("UTF-8")));
}
// Log the resulting hash as base64 String
logger.info("Legace password digest: salt=" + salt + " hash=" + Base64.getEncoder().encodeToString(hash));
}
Кто-нибудь видит проблему? Я думаю, что разница в результате: PHP: binary.binary и JAVA: addAll (байт [], байт [])
Заранее спасибо
Звучит неплохо и делает выделение смысла;) Я дам ему попробовать завтра.Только сейчас закончил писать сегодня –
В PHP-коде, если '$ this-> iterations'' '5000 и' $ i' инициализируется '1' в цикле for, тогда цикл for будет перебирать' 4,999' раз, не '5000 раз. И так как вы говорите, что первый раунд выполняется за пределами цикла в PHP-коде, то и PHP, и Java-код должны повторять «5000 раз». –
Вы правы, PHP-код выполняет итерацию 5000 (4999 + 1) раз. Однако код Java выполняет итерацию 5001 раз (5000 + 1), так как он также имеет начальный раунд вне цикла. Я смутил оба языка в своем ответе, извините. Я исправлю это. Я все еще думаю, что это корень проблемы. –