Авторизация SCRAM-SHA-1 через PHP

помогите мне, пожалуйста, с реализацией семантического кода из руководства по авторизации SCRAM-SHA-1 на сервере XMPP. Итак, мы получили:

clientFinalMessageBare = "c=biws,r=" .. serverNonce
saltedPassword = PBKDF2-SHA-1(normalizedPassword, salt, i)
clientKey = HMAC-SHA-1(saltedPassword, "Client Key")
storedKey = SHA-1(clientKey)
authMessage = initialMessage .. "," .. serverFirstMessage .. "," .. clientFinalMessageBare
clientSignature = HMAC-SHA-1(storedKey, authMessage)
clientProof = clientKey XOR clientSignature
clientFinalMessage = clientFinalMessageBare .. ",p=" .. base64(clientProof)

Мой PHP-код:

$cfmb = 'c=biws,r='.$salt;     
$saltpass = hash_pbkdf2('sha1', 'IDoMdGuFE9S0', $ps, $iter);        
//hash_pbkdf2('sha1', 'IDoMdGuFE9S0', $salt, $iter, 0, true); maybe like that???
$ckey = hash_hmac('sha1', $saltpass, 'Client Key');
$sckey = sha1($ckey);
$authmsg = $im.','.$chal.','.$cfmb;
$csign = hash_hmac('sha1', $sckey, $authmsg);
$cproof = bin2hex(pack('H*',$ckey) ^ pack('H*',$csign));
$cfm = $cfmb.',p='.base64_encode($cproof);

Где-то ошибка (может ВСЕ большая ошибка ;)) и мне очень нужна ваша помощь для исправления моего кода, может быть я использую неправильные функции или аргументы в неправильных позициях? Поскольку результат - сбой, сервер отправляет мне это:

«Ответ, предоставленный клиентом, не соответствует тому, который мы рассчитали».

PS: извините за мой плохой английский ;)


person Andrey Samozhenkov    schedule 23.09.2015    source источник


Ответы (1)


Прежде всего, очень запутанно использовать $salt для serverNonce и $ps для соли.

Но что еще более важно, вы должны позаботиться о том, чтобы отслеживать, возвращают ли используемые вами функции двоичные данные или строки в шестнадцатеричном коде. hash_pbkdf2, sha1 и hash_hmac по умолчанию возвращают шестнадцатеричные закодированные строки. Вы вызываете pack('H*', ...) для декодирования их для $cproof, но не при вычислении $ckey и $csign.

Гораздо проще вычислить двоичные данные напрямую, всегда передавая $raw_data = TRUE:

$cfmb = 'c=biws,r='.$salt;     
$saltpass = hash_pbkdf2('sha1', 'IDoMdGuFE9S0', $ps, $iter, 0, TRUE);        
$ckey = hash_hmac('sha1', 'Client Key', $saltpass, TRUE);
$sckey = sha1($ckey, TRUE);
$authmsg = $im.','.$chal.','.$cfmb;
$csign = hash_hmac('sha1', $authmsg, $sckey, TRUE);
$cproof = $ckey ^ $csign;
$cfm = $cfmb.',p='.base64_encode($cproof);

Кроме того, ваши hash_hmac вызовы были неверными: сначала данные, затем ключ.

person xnyhps    schedule 23.09.2015
comment
Братан, я видел твой комментарий на stackoverflow.com/questions/ 29298346/ и очень хочу задать вопрос напрямую вам, но не нашел где есть личные сообщения, а вы заходите сюда, спасибо!)) Да, соль - просто моя быстрая ошибка, когда я сделал тот демо-код, и это это я понимаю сразу после размещения моего сообщения. Так что, ок - чуть позже попробую все, что вы рекомендуете, а потом отчитаюсь здесь о результате! - person Andrey Samozhenkov; 23.09.2015
comment
Не могли бы вы помочь мне еще с одним вопросом, намного проще, чем этот? stackoverflow.com/questions/32728223/ - person Andrey Samozhenkov; 23.09.2015
comment
And something still wrong... Server First Message - is the full block [‹challenge xmlns=urn:ietf:params:xml:ns:xmpp-sasl› cj02ZDQ0MmI1ZDllNTFhNzQwZjM2OWUzZGNlY2YzMTc4ZWMxMmIzOTg1YmJkNGE4ZTZmODE0YjQyMmFiNzY2NTczLHM9UVNYQ1IrUTZzZWs4YmY5MixpPTQwOTY= ‹/challenge›] or ​​base64_decoded inner string? И тот же вопрос о первоначальном сообщении. И второй вопрос о конечном результате - MY_SEND_TO_SERVER_FUNCTION('‹ответ xmlns=urn:ietf:params:xml:ns:xmpp-sasl›’.base64_encode($cfm).’‹/response›'); Верно? Или мне нужно сделать что-то еще с результатом, прежде чем отправить его? - person Andrey Samozhenkov; 23.09.2015
comment
Первое сообщение сервера должно иметь форму r=abcabcabc,s=QSXCR+Q6sek8bf92,i=4096. Так что это не в кодировке base64 и без XML. Окончательное сообщение вашего клиента выглядит правильно. - person xnyhps; 23.09.2015