Вывод node.js hmac.digest () кажется неправильным - PullRequest
3 голосов
/ 18 декабря 2011

Я пытаюсь реализовать библиотеку Facebook с помощью node.js, и подпись запроса не работает.У меня есть пример PHP , показанный здесь , переведенный в узел.Я пробую это с примером, приведенным там, где секрет - это строка «секрет».Мой код выглядит так:

var signedRequest = request.signed_request.split('.');

var sig = b64url.decode(signedRequest[0]);

var expected = crypto.createHmac('sha256', 'secret').update(signedRequest[1]).digest();

console.log(sig == expected); // false

Я не могу console.log сами декодированные строки, потому что у них есть специальные символы, которые заставляют консоль очищаться (если у вас есть предложение обойти это, пожалуйста,я знаю) но я могу вывести их кодировку b64url.

Ожидаемый кодированный sig, как вы можете видеть в документации FB, равен

vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso

My expected, когдазакодировано, это

wr5Vw6DCu8KuAUBhUkLCtjRlw4JBZATCjMK9wovDkx7Dr0ZDRgzDtsK4w49Kw4o

Так почему я думаю, что это digest, что это неправильно?Может ошибка на моей стороне?Что ж, если я выполню точный пример в PHP, приведенный в документации, получится правильный результат.Но если я изменю вызов hash_hmac, чтобы последний параметр был ложным, выводя hex, я получу

YmU1NWUwYmJhZTAxNDA2MTUyNDJiNjM0NjVjMjQxNjQwNDhjYmQ4YmQzMWVlZjQ2NDM0NjBjZjZiOGNmNGFjYQ==

Теперь, если я вернусь к своему JavaScript-коду и изменим свой код HMAC на .digest("hex")вместо значения по умолчанию "binary" и записи в кодировке результата base64, я получаю ... сюрприз!

YmU1NWUwYmJhZTAxNDA2MTUyNDJiNjM0NjVjMjQxNjQwNDhjYmQ4YmQzMWVlZjQ2NDM0NjBjZjZiOGNmNGFjYQ

То же самое, за исключением того, что знаки == отсутствуют с конца, но я думаю, что этоконсольная вещь.Я не могу себе представить, что это проблема, без них это даже не допустимая длина строки base64.

Итак, почему метод дайджеста выводит правильный результат при использовании hex, но неправильный ответ при использовании двоичного?Разве двоичный файл не совсем совпадает с «необработанным» выводом эквивалента PHP?И если это так, как это правильно назвать?

Ответы [ 3 ]

1 голос
/ 18 декабря 2011

Мы обнаружили, что это действительно была ошибка в crypto lib, и это была известная проблема, зарегистрированная на github. Мы должны будем обновить и получить исправление.

0 голосов
/ 19 декабря 2011

Я партнер Тессерекса.Я полагаю, что ответ мог быть комбинацией как собственного сообщения Tesserex, так и ответа Juicy Scripter.Мы все еще использовали Node ver.0.4.7.Упомянутая ошибка, упомянутая Tesserex, может быть найдена здесь: https://github.com/joyent/node/issues/324. Я не совсем уверен, что эта ошибка затронула нас, но, похоже, это хорошая возможностьМы обновили Node до версии 0.6.5 и применили решение Juicy Scripter, и все теперь работает.Спасибо.

В качестве примечания о предложении использовать существующие библиотеки.Большинство существующих библиотек требуют экспресс, это то, что мы стараемся избегать, чтобы сделать некоторые из особенностей нашего приложения.Также существующие библиотеки обычно предполагают, что вы используете node.js как веб-сервер и отвечаете на запросы одного пользователя за раз.Мы используем постоянные соединения с веб-сокетами, и наш клиент Facebook будет обрабатывать данные сеанса для нескольких пользователей одновременно.В конце концов я надеюсь сделать наш клиент Facebook открытым исходным кодом для использования с такими приложениями, как наше.

0 голосов
/ 18 декабря 2011

На самом деле проблем с digest нет, результаты b64url.decode в кодировке utf8 по умолчанию (которую можно указать вторым параметром), если вы используете:

var sig = b64url.decode(signedRequest[0], 'binary');
var expected = crypto.createHmac('sha256', 'secret').update(signedRequest[1]).digest();
// sig === expected

signatureи результат дайджеста будет таким же.

Вы также можете проверить это, превратив digest результаты в utf8 кодированную строку:

var sig = b64url.decode(signedRequest[0]);
var expected = crypto.createHmac('sha256', 'secret').update(signedRequest[1]).digest();
var expected_buffer = new Buffer(expected_sig.digest(), 'binary');
// sig === expected_buffer.toString()

Также вы можете рассмотреть возможность использованияСуществующие библиотеки для выполнения такой работы (и, возможно, больше), если назвать несколько:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...