SCRAM-SHA-1 помогите имплементировать алгоритм на php

iNfantry

Новичок
Всем привет, очень прошу помощи с имплементацией на пхп нужного кода, собственно вот семантическое описание задачи:

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
serverKey = HMAC-SHA-1(saltedPassword, "Server Key")
serverSignature = HMAC-SHA-1(serverKey, authMessage)
clientFinalMessage = clientFinalMessageBare .. ",p=" .. base64(clientProof)

Мой вариант, но не работает правильно:
PHP:
$cfmb = 'c=biws,r='.$pr;
$saltpass = hash_pbkdf2('sha1', 'MyPass123', $ps, $pi);
$ckey = hash_hmac('sha1', $saltpass, 'Client Key');
$sckey = sha1($ckey);
$authmsg = $im1.','.$chal.','.$cfmb;
$csign = hash_hmac('sha1', $sckey, $authmsg);
$cproof = bin2hex(pack('H*',$ckey) ^ pack('H*',$csign));
$cfm = $cfmb.',p='.base64_encode($cproof);
Подскажите, что не так? Все переменные иницаилизированы правильными значениями само собой.

ЗЫ: Если есть кто хорошо разбирается в вопросе готов даже заплатить за помощь.
 

iNfantry

Новичок
base64_encode(bin2hex(...)) — явно что-то неправильное.
я наверное даже упрощу вопрос, просто конкретно вот эти моменты по отдельности правильно ли я в пхп-коде изобразил?

PBKDF2-SHA-1(normalizedPassword, salt, i)
HMAC-SHA-1(saltedPassword, "Client Key")
SHA-1(clientKey)
HMAC-SHA-1(storedKey, authMessage)
clientKey XOR clientSignature
HMAC-SHA-1(saltedPassword, "Server Key")
HMAC-SHA-1(serverKey, authMessage)

В частности больше всего мне непонятно насчет функции hash_pbkdf2() а именно какие параметры указать 5 и 6, я их просто опустил, но не факт что они ненужны... Вся эта лабуда - механизм авторизации джаббер-клиента и я весь день гуглил и ничего не смог найти кроме официальных рфц, но в них очень много для меня пробелов, таких как относительно этих двух аргументов например.
 

Вурдалак

Продвинутый новичок
В частности больше всего мне непонятно насчет функции hash_pbkdf2() а именно какие параметры указать 5 и 6
, 0, true, судя по всему.

И, кстати, необязательно юзать pack(), у hash_hmac последний аргумент сразу позволяет получить сырые данные.
 

iNfantry

Новичок
Что именно "то" не работает? Не бывает так, чтоб ыне работало неизвестно что.
Кто код писал?…
Что не работает - неправильно высчитывается параметр $cproof, вполне возможно по причине того что где-то чтото в хекс не переведено или еще както, вобщем я думаю гдето я неправильно что-то преобразую.
В работе опираюсь на этот рфц: http://tools.ietf.org/html/rfc5802 и на эту статью в википедии: https://ru.wikipedia.org/wiki/SCRAM#cite_note-RFC_5802.E2.80.942010.E2.80.94.E2.80.94-3

Сервер возвращает:
<failure...><text>The response provided by the client doesn&apos;t match the one we calculated.</text></failure>

Вся эта батва представляет собой кусок авторизации моего джаббер-клиента, всё прекрасно работало пока не потребовалось сделать именно новый механизм авторизации.
 

iNfantry

Новичок
Вот полный кусок кода для убедительности:
PHP:
$this->send('<?xml version="1.0"?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" version="1.0" xmlns="jabber:client" to="'.($this->domain).'" xml:lang="en" xmlns:xml="http://www.w3.org/XML/1998/namespace">');
        $xmlin = $this->read(); // получение ответа
        $im = '<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="SCRAM-SHA-1">'.
            base64_encode($im1='n,,'.($im2='n=bot,r='.($nonce=md5(microtime())))).'</auth>';
        $this->send($im);
        $xmlin = '<xml>'.($this->read()).'</xml>'; // получаем ответ
        $xmlob = @simplexml_load_string($xmlin);
        if (!$xmlob->challenge) {
            echo 'challenge error: '.$xmlin;
            return false;
        }
        $chal = base64_decode($xmlob->challenge[0]);
        $pr = $ps = $pi = null;
        $ed = explode(',', $chal);
        if (($sz=sizeof($ed))<3) echo 'parse error 1';
        else {
            for ($i=0, $sz=sizeof($ed); $i<$sz; $i++) {
                $ed1 = explode('=', $ed[$i], 2);
                if (sizeof($ed1)==2)
                    if ($ed1[0]=='r') $pr = $ed1[1];
                    elseif ($ed1[0]=='s') $ps = $ed1[1];
                    elseif ($ed1[0]=='i') $pi = $ed1[1];
            }
        }
        if (!isset($pr) || !isset($ps) || !isset($pi)) echo 'parse error 2';
        $ps = base64_decode($ps);
        $cfmb = 'c=biws,r='.$pr;
        $saltpass = hash_pbkdf2('sha1', 'MyPass123', $ps, $pi, 0, true);
        $ckey = hash_hmac('sha1', $saltpass, 'Client Key', true);
        $sckey = sha1($ckey, true);
        $authmsg = $im2.','.$chal.','.$cfmb;
        $csign = hash_hmac('sha1', $sckey, $authmsg, true);
        $cproof = $ckey ^ $csign;
        $cfm = $cfmb.',p='.base64_encode($cproof);
        $this->send('<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">'.base64_encode($cfm).'</response>');
        echo '['.$this->read().']';
Скорее всего гдето чтото в хексы перегнать надо или в бинарный вид, от огромного количества вариантов "что может быть не так" я и обращаюсь за помощью, сам перепробовал уже кучу всего. ;(
 
Сверху