0

I'm trying to verify the payload coming into my webhook from the TransferWise api.

API Link: https://api-docs.transferwise.com/#webhook-events-webhook-handlers

I've setup a public https endpoint via Google Cloud Functions.

index.ts

import { wiseWebhookTest } from "./wise/webHooks";

exports.wiseWebhookTest = functions.https.onRequest(wiseWebhookTest);

webHooks.ts

const livePublicKey = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvO8vXV+JksBzZAY6GhSO
XdoTCfhXaaiZ+qAbtaDBiu2AGkGVpmEygFmWP4Li9m5+Ni85BhVvZOodM9epgW3F
bA5Q1SexvAF1PPjX4JpMstak/QhAgl1qMSqEevL8cmUeTgcMuVWCJmlge9h7B1CS
D4rtlimGZozG39rUBDg6Qt2K+P4wBfLblL0k4C4YUdLnpGYEDIth+i8XsRpFlogx
CAFyH9+knYsDbR43UJ9shtc42Ybd40Afihj8KnYKXzchyQ42aC8aZ/h5hyZ28yVy
Oj3Vos0VdBIs/gAyJ/4yyQFCXYte64I7ssrlbGRaco4nKF3HmaNhxwyKyJafz19e
HwIDAQAB
-----END PUBLIC KEY-----`;

const sandboxPublicKey = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwpb91cEYuyJNQepZAVfP
ZIlPZfNUefH+n6w9SW3fykqKu938cR7WadQv87oF2VuT+fDt7kqeRziTmPSUhqPU
ys/V2Q1rlfJuXbE+Gga37t7zwd0egQ+KyOEHQOpcTwKmtZ81ieGHynAQzsn1We3j
wt760MsCPJ7GMT141ByQM+yW1Bx+4SG3IGjXWyqOWrcXsxAvIXkpUD/jK/L958Cg
nZEgz0BSEh0QxYLITnW1lLokSx/dTianWPFEhMC9BgijempgNXHNfcVirg1lPSyg
z7KqoKUN0oHqWLr2U1A+7kqrl6O2nx3CKs1bj1hToT1+p4kcMoHXA7kA+VBLUpEs
VwIDAQAB
-----END PUBLIC KEY-----`;

const SIGNATURE_HEADER = "X-Signature-SHA256";

const validatePayload = (
  sandbox = false,
  payload: any,
  signature: string
) => {

  const sig = crypto.createVerify("RSA-SHA1");
  sig.update(payload);
  const verified = sig.verify(
    sandbox ? sandboxPublicKey : livePublicKey,
    signature,
    "base64"
  );

  return verified;
};

const isValidSignature = (request: functions.https.Request): boolean => {

  const signature = request.get(SIGNATURE_HEADER) as string;

  return validatePayload(true, request.rawBody, signature);
};

export const wiseWebhookTest = (
  request: functions.https.Request,
  response: functions.Response
): Promise<void> => {

  if (!isValidSignature(request)) {
    sendError(response, "Invalid Signature");
    return Promise.resolve();
  }

  console.log(`Signature is valid`);

  // respond positively to Wise, even though we don't process it
  response.status(200).send({});

  return Promise.resolve();
};

The sig.verify() always returns false.

I'm testing in the TransferWise sandbox: https://sandbox.transferwise.tech/

Some of the above code is from: https://github.com/fightmegg/transferwise

Jeremy
  • 3,438
  • 3
  • 34
  • 57

1 Answers1

0

One part of the code has const SIGNATURE_HEADER = "X-Signature-SHA256"; while the second part has "RSA-SHA1" in there. I would definitely not recommend SHA-1 for signatures, so I'd upgrade that second code fragment to use SHA-256.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • 1
    I tried with SHA-256 and doesn't for me, i changed it to SHA256 and it worked. Incase you face the same problem, you can try my what works for me. Thanks for bringing this question forward Jeremy and thanks for the improvement Maarten. It was helpful – Sodruldeen Mustapha Jan 08 '22 at 10:39