Lahiru Chandima
Lahiru Chandima

Reputation: 24068

Verifying a RSA signature with nodejs (signed with phpseclib)

I am trying to integrate a payment gateway to my nodejs app. When the payment is complete, the gateway redirects the user to my site with the payment result. The result is RSA signed and I need to verify it with a public key provided by the payment gateway.

Following is the sample PHP code the payment gateway provides for signature verification.

<?php
include 'Crypt/RSA.php';
$rsa = new Crypt_RSA();
$payment = base64_decode($_POST ["payment"]);
$signature = base64_decode($_POST ["signature"]);
$publickey = "-----BEGIN PUBLIC KEY----- SOMEKEYSOMEKEYSOMEKEYSOMEKEYSOMEKEYSOMEKEYSOMEKEY -----END PUBLIC KEY-----";
$rsa->loadKey($publickey);
$signature_status = $rsa->verify($payment, $signature) ? TRUE : FALSE;
echo $signature_status; 
?>

The PHP code uses following encryption library for signature verification.

https://github.com/phpseclib/phpseclib

I tried the sample php code and it works.

I tried to verify the signature with the help of node-rsa library in following way.

const NodeRSA = require('node-rsa');
const decryptionKey = new NodeRSA(PUBLIC_KEY);
decryptionKey.setOptions({signingScheme: 'pss-sha1'});

module.exports.handlePaymentCallback = function (req, res, next) {
    const signature = Buffer.from(req.body.signature, 'base64').toString();
    const payment = Buffer.from(req.body.payment, 'base64').toString();
    let result = decryptionKey.verify(payment, signature);
}

But the signature verification fails. I tried changing the signingScheme to various possible schemes (pss-sha256, pkcs1-sha256, pkcs1-sha1, etc.) but it doesn't work.

I tried using nodejs crypto library too, but still failed.

const constants = process.binding('constants').crypto;
const crypt = require('crypto');

module.exports.handlePaymentCallback = function (req, res, next) {
    const signature = Buffer.from(req.body.signature, 'base64').toString();
    const payment = Buffer.from(req.body.payment, 'base64').toString();
    const verifier = crypt.createVerify('RSA-SHA1');
    verifier.update(new Buffer('' + payment, 'utf8'));
    const options = {key: PUBLIC_KEY};
    let result = verifier.verify(options, signature);
}

Does anyone know how to get this done?

Upvotes: 1

Views: 5051

Answers (1)

Lahiru Chandima
Lahiru Chandima

Reputation: 24068

I found the problem. I have called toString() of signature and payment buffers unnecessarily. When toString() is removed, it works.

const NodeRSA = require('node-rsa');
const decryptionKey = new NodeRSA(PUBLIC_KEY);
decryptionKey.setOptions({signingScheme: 'pss-sha1'});

module.exports.handlePaymentCallback = function (req, res, next) {
    const signature = Buffer.from(req.body.signature, 'base64');
    const payment = Buffer.from(req.body.payment, 'base64');
    let result = decryptionKey.verify(payment, signature);
}

Upvotes: 3

Related Questions