2016-04-28 16 views
4

Ich habe Code, der in meiner PHP-App funktioniert. Im PHP melde ich die URL mit dem folgenden Code:Hash_hmac entspricht in Node.js

private static function __getHash($string) 
{ 
    return hash_hmac('sha1', $string, self::$__secretKey, true);  
} 

Ich bin versucht, die URL in der gleichen Art und Weise in einer Node.js Anwendung zu unterzeichnen. Das ist, was ich versuche:

S3.prototype.getHash = function(string){ 
    var key = this.secret_key; 
    var hmac = crypto.createHash('sha1', key); 
    hmac.update(string); 
    return hmac.digest('binary'); 
}; 

Allerdings bin ich die folgende Fehlermeldung erhalten:

The request signature we calculated does not match the signature you provided. Check your key and signing method.

Haben diese Teile des Codes das gleiche tun? Fehle ich etwas?

+0

Vergleichen Sie die Ausgaben der beiden Hashes, um zu sehen, ob sie das gleiche tun. – Brody

+0

Für den Anfang nimmt die 'crypto.createHash' Methode in Node keinen Schlüssel, weil sie einen Hash berechnet, nicht einen HMAC. – Chris

+0

@Chris, also würde das Ändern zu 'createHmac' theoretisch das Problem lösen? –

Antwort

1

Das Hauptproblem hier ist, dass Sie createHash verwenden, die einen Hash erstellt, anstatt createHmac, die einen HMAC erstellt.

Ändern createHash zu createHmac und Sie sollten feststellen, dass es das gleiche Ergebnis produziert.

Dies ist die Ausgabe, die Sie erwarten sollten:

chris /tmp/hmac $ cat node.js 
var crypto = require('crypto'); 
var key = 'abcd'; 
var data = 'wxyz'; 

function getHash(string){ 
    var hmac = crypto.createHmac('sha1', key); 
    hmac.update(string); 
    return hmac.digest('binary'); 
}; 

process.stdout.write(getHash(data)); 

chris /tmp/hmac $ cat php.php 
<?php 
$key = "abcd"; 
$data = "wxyz"; 
function __getHash($string) 
{ 
    global $key; 
    return hash_hmac('sha1', $string, $key, true); 
} 

echo utf8_encode(__getHash($data)); 

chris /tmp/hmac $ node node.js | base64 
WsOKw4xgw4jDlFHDl3jDuEPDuCfCmsOFwoDCrsK/w6ka 
chris /tmp/hmac $ php php.php | base64 
WsOKw4xgw4jDlFHDl3jDuEPDuCfCmsOFwoDCrsK/w6ka 
+0

Ich bekomme immer noch dass die Signatur nicht übereinstimmt. Irgendeine Idee warum? –

+0

Nun, wie vergleichen Sie die Binärdaten? Wenn Sie sie als Zeichenfolgen vergleichen, müssen Sie sicherstellen, dass die Codierung korrekt ist. Ich habe die Ausgabe angehängt, die ich bekomme. Hinweis Ich habe die PHP-Ausgabe von latin-1 in UTF-8- und base64-codierte beide Ausgaben konvertiert, um einen einfachen Vergleich zu ermöglichen. – Chris

+0

Sara: hash_hmac erzeugt standardmäßig einen Hex-Digest – keyvan

2

Diese Antwort von Chris ist gut, wenn man hash_hmac mit dem letzten Parameter true sein portieren. In diesem Fall wird eine Binärdatei erzeugt, wie es bei Chris's Javascript der Fall ist.

zu, dass dieses Beispiel hinzu:

$sign = hash_hmac('sha512', $post_data, $secret); 

Würde mit einer Funktion wie so in NodeJS portiert werden:

const crypto = require("crypto"); 

function signHmacSha512(key, str) { 
    let hmac = crypto.createHmac("sha512", key); 
    let signed = hmac.update(new Buffer(str, 'utf-8')).digest("hex"); 
    return signed 
} 

Der hier Unterschied, dass, wenn Sie das letzte Argument weglassen zu hash_hmac (oder setze es auf etwas nicht true), verhält es sich wie in der PHP docs definiert:

When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits.

Um dies mit node.js zu tun, verwenden wir digest('hex'), wie Sie im Snippet sehen können.