Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hashes not similar between PHP and Paw REST Client

I'm building a HMAC API and I have issues testing the hashing with Paw.

On Paw I have this payload:

GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout

and a custom HMAC-SHA256 variable (actually function like this that sets it in the X-Hash header.

X-Hash: 4Cq2yehWumDcUk1dYyfhm6qWjJVBkOCB8o12f5l0WGE=

In my PHP API I have the same thing:

GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout

and used:

hash_hmac('sha256', $this->getPayload(), '9a6e30f2016370b6f2dcfb6880501d7f2305d69bout', false);

So when comparing the hashes:

Paw: 4Cq2yehWumDcUk1dYyfhm6qWjJVBkOCB8o12f5l0WGE=
PHP: 6961b9d1f6e986c49d963cbebd691fa68dfa59b4ce3b7f05320c2d43eae3c7c3

They are very different. Any idea why is that?

Update

Paw Code:

function evaluate(context){
  var loc = getLocation(context.getCurrentRequest().url);

  var payload = "";
  payload += context.getCurrentRequest().method + ':';
  payload += loc.pathname + ':';
  payload += JSON.stringify(context.getCurrentRequest().body) + ':';
    payload += "9a6e30f2016370b6f2dcfb6880501d7f2305d69bout"; // Private key
  return payload;
};

function getLocation(href) {
    var match = href.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)(\/[^?#]*)(\?[^#]*|)(#.*|)$/);
    return match && {
        protocol: match[1],
        host: match[2],
        hostname: match[3],
        port: match[4],
        pathname: match[5],
        search: match[6],
        hash: match[7]
    }
}

PHP Code (with lots of comments):

if (strpos(strtoupper($authHeader), 'HMAC') !== 0) {
    echo 'out';
    throw new HttpForbiddenException();
}
else {
    $hmacSignature = $app->request->headers()->get('X-Hash');
    $publicKey = $app->request->headers()->get('X-Public');

    if ( empty($hmacSignature) || empty($publicKey) ) {
        echo 'out2';
        throw new HttpForbiddenException();
    }
    else {

        $this->hmacManager->setPublicKey($publicKey);
        print '$publickey = ' . $publicKey . '<br>';

        // Validate if base64_encoded or not
        if( base64_decode($hmacSignature, true) !== FALSE ) {
            $binaryString = base64_decode($hmacSignature);
            $hmacSignature = bin2hex($binaryString);
            print 'decoding ' . '<br>';
        }
        $this->hmacManager->setHmacSignature($hmacSignature);
        print '$hmacSignature = ' . $hmacSignature . '<br>';

        $this->hmacManager->setRequestMethod($app->request->getMethod());
        print 'method = ' . $app->request->getMethod() . '<br>';
        $this->hmacManager->setRequestResourceUri($app->request->getResourceUri());
        print 'uri = ' . $app->request->getResourceUri() . '<br>';

        $requestBody = $app->request()->getBody();
        if (Utils::isJson($requestBody)) {
            $requestBody = json_decode($requestBody);
        }
        $this->hmacManager->setRequestBody(json_encode($requestBody));
        print 'body = ' . json_encode($requestBody) . '<br>';

        print 'private key = ' . $this->hmacManager->getPrivateKey() . '<br>';

        $payload = '';
        $payload .= $this->hmacManager->getRequestMethod() . ":";
        $payload .= $this->hmacManager->getRequestResourceUri() . ":";
        $payload .= $this->hmacManager->getRequestBody() . ":";
        $payload .= $this->hmacManager->getPrivateKey();
        print 'PHP payload [' . $payload . ']';
        $this->hmacManager->setPayload($payload);

        $hmacValue = $this->hmacManager->generateHmac();
        $isValid = $this->hmacManager->isValid($this->hmacManager->generateHmac(), $hmacSignature);

        if ($isValid !== true) {
            echo 'out3';
            throw new HttpForbiddenException();
        }
    }
}

generateHmac from another class:

public function generateHmac()
{
    print 'Generating HMAC' . '<br>';
    $algorithm = $this->getAlgorithm();
    print 'algo ' . $algorithm . '<br>';
    $privateKey = $this->getPrivateKey();
    print 'privk ' . $privateKey . '<br>';

    if (empty($algorithm)) {
        throw new \RuntimeException('Algorithm must be set and not empty');
    } elseif (empty($privateKey)) {
        throw new \RuntimeException('Private key must be set and not empty');
    }

    print 'payload ' . $this->getPayload() . '<br>';
    $hash = hash_hmac($this->getAlgorithm(), $this->getPayload(), $this->getPrivateKey(), false);
    print 'php hasj: ' . $hash . '<br>';

    return $hash;
}

Finally, here's the output statements:

$publickey = 95f97b93560f951b4cae46c86d03d9b1a81d4ae8
decoding 
$hmacSignature = e02ab6c9e856ba60dc524d5d6327e19baa968c954190e081f28d767f99745861

method = GET
uri = /hello/world
body = ""
private key = 9a6e30f2016370b6f2dcfb6880501d7f2305d69bout
PHP payload [GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout]

Generating HMAC
algo sha256
privk 9a6e30f2016370b6f2dcfb6880501d7f2305d69bout
payload GET:/hello/world:"":9a6e30f2016370b6f2dcfb6880501d7f2305d69bout
php hash: 6961b9d1f6e986c49d963cbebd691fa68dfa59b4ce3b7f05320c2d43eae3c7c3

Hope it helps!

like image 847
Vallieres Avatar asked Apr 30 '15 19:04

Vallieres


Video Answer


2 Answers

The paw hash is base64 encoded while the PHP one is in hexadecimal. So decode the paw hash first:

$binary = base64_decode($pawHash);
$hex = bin2hex($binary);

And then compare this to your own hash.

like image 180
laurent Avatar answered Sep 22 '22 20:09

laurent


We've just added new Base 64 to Hex conversion dynamic values, this should solve your problem.

Wrap your HMAC signature dynamic value inside the new Base 64 to Hex one, and you'll get a valid hexadecimal signature:

Hexadecimal HMAC signature with Paw

You can install this new dynamic value here: Base 64 to Hex Dynamic Value

like image 33
Micha Mazaheri Avatar answered Sep 25 '22 20:09

Micha Mazaheri