Функция кодировщика паролей Symfony2 в Javascript

Я создал приложение Symfony2, используя FOSUserBundle и FOSRestBundle. Я хотел бы подключить другое приложение к моему приложению Symfony, используя rest API. Мне нужно написать функцию кодирования паролей Symfony на Javascript. На самом деле в PHP это выглядит так:

$salt = "secret";
$password = "azerty";
$salted = $password.'{'.$salt.'}';
$digest = hash('sha512', $salted, true);

for ($i = 1; $i < 5000; $i++) {
    $digest = hash('sha512', $digest.$salted, true);
}
$digest = base64_encode($digest);

return $digest;

В Javascript я пытался использовать библиотеку CryptoJS. Мой код:

var salt = 'secret',
    password = 'azerty',
    salted = password + '{' + salt + '}'
    digest = CryptoJS.SHA512(salted);

for (var i=1; i<5000; i++) {
    digest = CryptoJS.SHA512(digest+salted);
}

digest = digest.toString(CryptoJS.enc.Base64);

return digest;

Но угадайте, что? Это не работает, и я не знаю, почему. Кто-нибудь может помочь, пожалуйста? :)

С уважением, Колзак.


person Colzak    schedule 19.09.2014    source источник
comment
Что означает It does not work?   -  person Xatenev    schedule 19.09.2014
comment
Да, извините, я должен был сказать, что возвращаемый дайджест уже не тот. PHP возвращает ZBNCDQnUk31GBE5y10AG5MUbEzsN9kNGmiORRMTss + DiwtDtRaFJwjoMJQFp7mMTfgvrm8GrUx0q87hmYNYihw == И Javascript возвращает q2lsiVES6m + Bxmzz87jk5z8epHE + jcd8tfIcIBWVx3KBuke + F9HuaahTHkhvqJDNASxw5mFEWgc2eng44Z8yKA ==   -  person Colzak    schedule 19.09.2014
comment
@Colzak: Чего вы на самом деле пытаетесь достичь? Это выглядит действительно пугающе.   -  person lxg    schedule 19.09.2014
comment
@lxg Я хотел скопировать функцию кодирования пароля Symfony, чтобы избежать отправки пароля пользователя через вызов API. На стороне клиента я получаю только соль пароля пользователя, поэтому, когда он вводит свой пароль, я генерирую соответствующий хеш, который отправляется на сервер и сравнивается с тем, что есть в БД. При этом пароль никогда не передается через вызовы API.   -  person Colzak    schedule 19.09.2014
comment
Во всяком случае, я думаю, что нет никакого решения этой проблемы. На другом языке (например, java) я видел рабочий пример, но в Javascript, я думаю, он немного сложнее. Может быть, вместо этого я мог бы просто закодировать пароль base64_encode и отправить его через https... idk.   -  person Colzak    schedule 19.09.2014
comment
Ну, это не мое дело, но я бы рекомендовал подход, основанный на одноразовом токене. Или используйте OAuth.   -  person lxg    schedule 19.09.2014
comment
Либо решение с токеном/oauth, предложенное @lxg, либо посмотрите, поддерживает ли этот API SSL/TLS.   -  person Jovan Perovic    schedule 19.09.2014


Ответы (2)


Хорошо, ответ @timothymctim помог мне. На самом деле, я думаю, что это проблема с кодировкой символов. Вот (странное) решение:

PHP:

$salt = "secret";
$password = "azerty";
$salted = $password.'{'.$salt.'}';
$digest = hash('sha512', $salted, true);

for ($i = 1; $i < 5000; $i++) {
    $digest = hash('sha512', utf8_encode($digest).$salted, true);
}
$digest = base64_encode($digest);

return $digest;

И Javascript:

var salt = 'secret',
password = 'azerty',
salted = password + '{' + salt + '}'
digest = CryptoJS.SHA512(salted);

for (var i=1; i<5000; i++) {
    digest = CryptoJS.SHA512(digest.toString(CryptoJS.enc.Latin1)+salted);
}

digest = digest.toString(CryptoJS.enc.Base64);

return digest;

Я не знаю, что думать. Все равно спасибо всем кто помог!

person Colzak    schedule 19.09.2014

Это не работает, потому что «хэш, который вы возвращаете, еще не является строкой. Это объект WordArray. Когда вы используете объект WordArray в строковом контексте, он автоматически преобразуется в шестнадцатеричную строку». (источник) С помощью digest = CryptoJS.SHA512(digest+salted); дайджест преобразуется в шестнадцатеричную строку. Если вы измените свой PHP-код на

$salt = "secret";
$password = "azerty";
$salted = $password.'{'.$salt.'}';
$digest = hash('sha512', $salted, false);

for ($i = 1; $i < 5000; $i++) {
    $digest = hash('sha512', $digest.$salted, false);
}

return $digest;

и вернуть дайджест в виде шестнадцатеричной строки (подойдет digest + '' или digest.toString(CryptoJS.enc.Hex)), это сработает. Я не уверен, как изменить код JavaScript, чтобы он соответствовал исходному коду PHP.

person timothymctim    schedule 19.09.2014
comment
Спасибо за ответ. Я понял, что вы имели в виду, но, к сожалению, мне нужно, чтобы php функционировал как есть. Я не знаю, существует ли какое-либо решение. Я попробую еще несколько вещей, но, думаю, мне придется сделать по-другому. - person Colzak; 19.09.2014