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_request
Nutzlast generieren, aber das stimmt nicht mit der signed_request
Signatur ü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_hmac
verwendet 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)