[FIXED] Validieren Sie die Signatur von Facebook signed_request in Javascript

Ausgabe

Ich baue eine Facebook-Seiten-App in Classic ASP. Ich konnte die Signatur, die Facebook als ersten Teil des POSTed an die App übergibt, nicht zuordnen signed_request.

Da es in VBScript nur wenige Bibliotheken für die Kryptografie gibt, verwende ich serverseitiges Javascript und die crypto-js-Bibliothek von https://code.google.com/archive/p/crypto-js/

Ich habe versucht, das PHP-Codebeispiel aus der Facebook-Dokumentation unter https://developers.facebook.com/docs/games/gamesonfacebook/login#parsingsr in Javascript zu übersetzen. Ich kann einen HMAC SHA256-Hash der signed_requestNutzlast generieren, aber das stimmt nicht mit der signed_requestSignatur überein.

Ich denke, das Problem ist, dass die Signatur von Facebook in einem anderen Format vorliegt. Es scheint binär zu sein ( ~1抚Ö….. ), während der HMAC SHA256-Hash, den ich erzeuge, eine hexadezimale Zeichenfolge ist ( 7f7e8f5f….. ). Im PHP-Beispiel von Facebook hash_hmacverwendet die Funktion den rohen binären Parameter. Ich denke also, ich muss entweder die Facebook-Signatur in Hexadezimal oder meine Signatur in Binär umwandeln, um einen “Äpfel-zu-Äpfel”-Vergleich durchzuführen und eine Übereinstimmung zu erhalten.

Hier ist mein Code:

/* Use the libraries from https://code.google.com/archive/p/crypto-js/
crypto-js/crypto-js.min.js
crypto-js/hmac-sha256.min.js
crypto-js/enc-base64.min.js
*/

var signedRequest = Request.queryString("signed_request")

var FB_APP_SECRET = "459f038.....";

var arSR = signedRequest.split(".");
var encodedSig = arSR[0];
var encodedPayload = arSR[1];

var payload = base64UrlDecode(encodedPayload);
var sig = base64UrlDecode(encodedSig);

var expectedSig;

expectedSig = CryptoJS.HmacSHA256(encodedPayload, FB_APP_SECRET); // Unaltered payload string; no match
expectedSig = CryptoJS.HmacSHA256(payload, FB_APP_SECRET); // base64-decoded payload string; no match

if (sig == expectedSig) {
    Response.write(payload);
} else {
    Response.write("Bad signature");
}

function base64UrlDecode(input) {
    // Replace characters and convert from base64.
    return Base64.decode(input.replace("-", "+").replace("_", "/"));
}

Lösung

Nachdem ich in der crypto-js-Dokumentation über die Codierung nachgesehen hatte, fand ich die Lösung. Die von crypto-js bereitgestellten De-/Codierungsmethoden sind unter „Encoders“ unten auf https://code.google.com/archive/p/crypto-js/ aufgeführt (Danke für den Schubs, CBroe.)

Die Lösung bestand darin, .toString()die Signaturen zu verwenden. Es scheint, als würde Crypto-js ein Wortformat verwenden, das eine Vergleichsübereinstimmung verhinderte. Ich habe auch auf die von crypto-js bereitgestellte base64-Decodierung umgestellt, um bei einer Bibliothek zu bleiben.

Hier ist mein aktualisierter Code:

/* Use the libraries from https://code.google.com/archive/p/crypto-js/
crypto-js/crypto-js.min.js
crypto-js/hmac-sha256.min.js
crypto-js/enc-base64.min.js
*/

var signedRequest = Request.queryString("signed_request")

var FB_APP_SECRET = "459f038.....";

var arSR = signedRequest.split(".");
var encodedSig = arSR[0];
var encodedPayload = arSR[1];

var payload = base64UrlDecode(encodedPayload);
var sig = base64UrlDecode(encodedSig);

var expectedSig = CryptoJS.HmacSHA256(encodedPayload, FB_APP_SECRET); /******** Correct payload */

if (sig.toString() != expectedSig.toString()) { /******* Use .toString() to convert to normal strings */
    Response.write(payload);
} else {
    Response.write("Bad signature");
}

function base64UrlDecode(input) {
    return CryptoJS.enc.Base64.parse( /******** Decode */
        input.replace("-", "+").replace("_", "/") // Replace characters
    );
}


Beantwortet von –
Chris


Antwort geprüft von –
Terry (FixError Volunteer)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like