0

I'm trying to convert this Node JS code to ASP.NET C#:

    const crypto = require('crypto');
/**
 * Validates a billing service webhook
 *
 * @param {string} req    Node request object, where 'req.body' is a Node
 *                        Buffer object containing the request body
 * @param {string} secret the secret string saved in the service App
 */
const isValidSignature = (req, secret) => {
  const fsSignature = req.headers['X-FS-Signature'];
  const computedSignature = crypto.createHmac('sha256', secret)
    .update(req.body)
    .digest()
    .toString('base64');
  return fsSignature === computedSignature;
}

Here is my attempt in C#

    private bool CheckNotificationValidContextual(string varRequestHashValue, string varMessageBody) // #2047
    {

        // This involves a test of the webhook functionality using ngroks and Postman
        // to send values that were previously generated from a test webhook from billing service
        // to a local development copy of the seller application (running in Visual Studio)
        // where the inputs are:
        // varRequestHashValue = Request.Headers["X-Fs-Signature"];
        // varMessageBody = new System.IO.StreamReader(Request.InputStream).ReadToEnd();

        // get the local copy of the webhook secret key from the local web config file
        var AMPTK_FSP_HMAC_SHA256_Key = ConfigVal.AMPTK_FSP_HMAC_SHA256();

        // convert the local copy of the secret key to a byte array
        byte[] AMPTK_keyBytes = Encoding.UTF8.GetBytes(AMPTK_FSP_HMAC_SHA256_Key);

        // create a hash object with the local copy of the secret key
        var _hashObjectOfLocalKey = new HMACSHA256(AMPTK_keyBytes);

        // convert the input webhook message body to a byte array
        byte[] _messageBodyByteArray = Encoding.UTF8.GetBytes(varMessageBody);

        // create a hash byte array of the message body byte array
        // using the hash object based on the local copy of the webhook secret
        byte[] _computedMessageHashBytes = _hashObjectOfLocalKey.ComputeHash(_messageBodyByteArray);

        // convert the hash byte array of the message body to a string
        string _stringOfComputedMessageHashBytes = Encoding.UTF8.GetString(_computedMessageHashBytes, 0, _computedMessageHashBytes.Length);

            // remove dashes and convert to lowercase
            _stringOfComputedMessageHashBytes= BitConverter.ToString(_computedMessageHashBytes).Replace("-", "").ToLower();


        // compare the string of the computed message body hash
        // to the received webhook secret hash value from Request.Headers["X-Fs-Signature"]
        if (_stringOfComputedMessageHashBytes == varRequestHashValue)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

The C# code compiles and runs ok.

The result I'm looking for is:

prNdADI26M0ov5x6ZlMr2J2zzB8z2TJRBDy+8gjPttk=

What I'm getting from the C# code "_stringOfComputedMessageHashBytes"

is this:

f37cdae653e167e36c8ed17e44ffa456832dbb7dcec1d00dc1b44a1234965e73

I've checked the inputs carefully (could still be wrong).

Question: have I translated the Node code properly to C#, and if not, how can I improve it? Or what else might be off?

Thanks!

1 Answer 1

1

I checked your C# code for computing hash, in general looks ok, you used correct library and correct class HMACSHA256 to calculate HMAC_SHA256 hash. The problem seems on the part that you were trying to convert the computed hash value to a base 64 string. You can use Convert.ToBase64String method to convert your byte array to base 64 string.

Here below you can find your updated C# code(I did minor improvements and updated the code to find _stringOfComputedMessageHashBytes).

I tested the hash results generated from node.js and C#, now they are both generating the same hash result:

    private bool CheckNotificationValidContextual(string varRequestHashValue, string varMessageBody) // #2047
    {
        // This involves a test of the webhook functionality using ngroks and Postman
        // to send values that were previously generated from a test webhook from billing service
        // to a local development copy of the seller application (running in Visual Studio)
        // where the inputs are:
        // varRequestHashValue = Request.Headers["X-Fs-Signature"];
        // varMessageBody = new System.IO.StreamReader(Request.InputStream).ReadToEnd();

        // get the local copy of the webhook secret key from the local web config file
        var AMPTK_FSP_HMAC_SHA256_Key = ConfigVal.AMPTK_FSP_HMAC_SHA256();

        // convert the local copy of the secret key to a byte array
        var AMPTK_keyBytes = Encoding.UTF8.GetBytes(AMPTK_FSP_HMAC_SHA256_Key);

        // create a hash object with the local copy of the secret key
        using (var _hashObjectOfLocalKey = new HMACSHA256(AMPTK_keyBytes))
        {
            // convert the input webhook message body to a byte array
            var _messageBodyByteArray = Encoding.UTF8.GetBytes(varMessageBody);

            // create a hash byte array of the message body byte array
            // using the hash object based on the local copy of the webhook secret
            var _computedMessageHashBytes = _hashObjectOfLocalKey.ComputeHash(_messageBodyByteArray);

            var _stringOfComputedMessageHashBytes = Convert.ToBase64String(_computedMessageHashBytes);

            // compare the string of the computed message body hash
            // to the received webhook secret hash value from Request.Headers["X-Fs-Signature"]
            return _stringOfComputedMessageHashBytes == varRequestHashValue;
        }
    }
Sign up to request clarification or add additional context in comments.

1 Comment

Works slick. I appreciate the guidance. Thanks**n.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.