private function _generateResponse($challenge, $password)
    {
        // XXX: as I don't support mandatory extension, I would fail on them.
        // And I simply ignore any optional extension.
        $matches = [];
        $server_message_regexp = "#^r=([\x21-\x2B\x2D-\x7E]+),s=((?:[A-Za-z0-9/+]{4})*(?:[A-Za-z0-9]{3}=|[A-Xa-z0-9]{2}==)?),i=([0-9]*)(,[A-Za-z]=[^,])*$#";
        if (!isset($this->cnonce, $this->gs2_header)
            || !preg_match($server_message_regexp, $challenge, $matches))
        {
            return false;
        }
        $nonce = $matches[1];
        $salt = base64_decode($matches[2]);
        if (!$salt)
        {
            // Invalid Base64.
            return false;
        }
        $i = intval($matches[3]);

        $cnonce = substr($nonce, 0, strlen($this->cnonce));
        if ($cnonce <> $this->cnonce)
        {
            // Invalid challenge! Are we under attack?
            return false;
        }

        $channel_binding = 'c=' . base64_encode($this->gs2_header); // TODO: support channel binding.
        $final_message = $channel_binding . ',r=' . $nonce; // XXX: no extension.

        // TODO: $password = $this->normalize($password); // SASLprep profile of stringprep.
        $saltedPassword = $this->hi($password, $salt, $i);
        $this->saltedPassword = $saltedPassword;
        $clientKey = call_user_func($this->hmac, $saltedPassword, "Client Key", TRUE);
        $storedKey = call_user_func($this->hash, $clientKey, TRUE);
        $authMessage = $this->first_message_bare . ',' . $challenge . ',' . $final_message;
        $this->authMessage = $authMessage;
        $clientSignature = call_user_func($this->hmac, $storedKey, $authMessage, TRUE);
        $clientProof = $clientKey ^ $clientSignature;
        $proof = ',p=' . base64_encode($clientProof);

        return $final_message . $proof;
    }
private function _generateResponse($challenge, $password)
    {
        // XXX: as I don't support mandatory extension, I would fail on them.
        // And I simply ignore any optional extension.
        $matches = [];
        $server_message_regexp = "#^r=([\x21-\x2B\x2D-\x7E]+),s=((?:[A-Za-z0-9/+]{4})*(?:[A-Za-z0-9]{3}=|[A-Xa-z0-9]{2}==)?),i=([0-9]*)(,[A-Za-z]=[^,])*$#";
        if (!isset($this->cnonce, $this->gs2_header)
            || !preg_match($server_message_regexp, $challenge, $matches))
        {
            return false;
        }
        $nonce = $matches[1];
        $salt = base64_decode($matches[2]);
        if (!$salt)
        {
            // Invalid Base64.
            return false;
        }
        $i = intval($matches[3]);

        $cnonce = substr($nonce, 0, strlen($this->cnonce));
        if ($cnonce <> $this->cnonce)
        {
            // Invalid challenge! Are we under attack?
            return false;
        }

        $channel_binding = 'c=' . base64_encode($this->gs2_header); // TODO: support channel binding.
        $final_message = $channel_binding . ',r=' . $nonce; // XXX: no extension.

        // TODO: $password = $this->normalize($password); // SASLprep profile of stringprep.
        $saltedPassword = $this->hi($password, $salt, $i);
        $this->saltedPassword = $saltedPassword;
        $clientKey = call_user_func($this->hmac, $saltedPassword, "Client Key", TRUE);
        $storedKey = call_user_func($this->hash, $clientKey, TRUE);
        $authMessage = $this->first_message_bare . ',' . $challenge . ',' . $final_message;
        $this->authMessage = $authMessage;
        $clientSignature = call_user_func($this->hmac, $storedKey, $authMessage, TRUE);
        $clientProof = $clientKey ^ $clientSignature;
        $proof = ',p=' . base64_encode($clientProof);

        return $final_message . $proof;
    }
private function _generateResponse ( $ challenge , $ password ) { // XXX: as I don't support mandatory extension, I would fail on them. // And I simply ignore any optional extension. $ matches = [ ] ; $ server_message_regexp = "#^r=([\x21-\x2B\x2D-\x7E]+),s=((?:[A-Za-z0-9/+]{4})*(?:[A-Za-z0-9]{3}=|[A-Xa-z0-9]{2}==)?),i=([0-9]*)(,[A-Za-z]=[^,])*$#" ; if ( ! isset ( $ this -> cnonce , $ this -> gs2_header ) || ! preg_match ( $ server_message_regexp , $ challenge , $ matches ) ) { return false ; } $ nonce = $ matches [ 1 ] ; $ salt = base64_decode ( $ matches [ 2 ] ) ; if ( ! $ salt ) { // Invalid Base64. return false ; } $ i = intval ( $ matches [ 3 ] ) ; $ cnonce = substr ( $ nonce , 0 , strlen ( $ this -> cnonce ) ) ; if ( $ cnonce <> $ this -> cnonce ) { // Invalid challenge! Are we under attack? return false ; } $ channel_binding = 'c=' . base64_encode ( $ this -> gs2_header ) ; // TODO: support channel binding. $ final_message = $ channel_binding . ',r=' . $ nonce ; // XXX: no extension. // TODO: $password = $this->normalize($password); // SASLprep profile of stringprep. $ saltedPassword = $ this -> hi ( $ password , $ salt , $ i ) ; $ this -> saltedPassword = $ saltedPassword ; $ clientKey = call_user_func ( $ this -> hmac , $ saltedPassword , "Client Key" , TRUE ) ; $ storedKey = call_user_func ( $ this -> hash , $ clientKey , TRUE ) ; $ authMessage = $ this -> first_message_bare . ',' . $ challenge . ',' . $ final_message ; $ this -> authMessage = $ authMessage ; $ clientSignature = call_user_func ( $ this -> hmac , $ storedKey , $ authMessage , TRUE ) ; $ clientProof = $ clientKey ^ $ clientSignature ; $ proof = ',p=' . base64_encode ( $ clientProof ) ; return $ final_message . $ proof ; }
Parses and verifies a non-empty SCRAM challenge.

@param  string $challenge The SCRAM challenge
@return string|false      The response to send; false in case of wrong challenge or if an initial response has not
been generated first.
@access private
Parses and verifies a non - empty SCRAM challenge .