Skip to main content

Checksum Generation

Checksum Generation

Checksum(Signature) generation logic:

We need to securely verify the validity of API requests and callbacks to ensure its data integrity.

  • All server-server communication should be signed using the following method. Any data where the signature does not match, should be discarded  with error response message, “Signature does not match”.

  • The Secret Key should be kept secure. In case it is compromised, an attacker has a chance to simulate payments. (however, we will be entertaining requests only from whitelisted IP-addresses for server calls)

  • The checksum signature will be calculated over the whole JSON payload. HMAC Hexdigest using SHA256 using the <PARTNER-SECRET-KEY>.

  • The checksum will be appended in the Header of API requests as a header attribute named X-Body-Signature . The HMAC will be calculated  over the JSON Stringified version of JSON.

See below how to calculate the HMAC-SHA256 in different languages:

JAVA:

/**
* This class defines common routines for generating
* authentication signatures for Razorpay Webhook requests.
*/
public class Signature
{
  private static final String HMAC_SHA256_ALGORITHM = "HmacSHA256";


  /**
  * Computes RFC 2104-compliant HMAC signature.
  * * @param data
  * The data to be signed.
  * @param key
  * The signing key.
  * @return
  * The Base64-encoded RFC 2104-compliant HMAC signature.
  * @throws
  * java.security.SignatureException when signature generation fails
  */
  public static String calculateRFC2104HMAC(String data, String secret)
  throws java.security.SignatureException
  {
      String result;
      try {

          // get an hmac_sha256 key from the raw secret bytes
          SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), HMAC_SHA256_ALGORITHM);

          // get an hmac_sha256 Mac instance and initialize with the signing key
          Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
          mac.init(signingKey);

          // compute the hmac on input data bytes
          byte[] rawHmac = mac.doFinal(data.getBytes());

          // base64-encode the hmac
          result = DatatypeConverter.printHexBinary(rawHmac).toLowerCase();

      } catch (Exception e) {
          throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
      }
      return result;
  }
}

PHP:

$hash = hash_hmac('sha256', $body, $secret);

C#:

//add following usings to file
using System;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;

//add below function to calculate the HMAC
private static byte[] HashHMAC(byte[] key, byte[] message)
{
  var hash = new HMACSHA256(key);
  byte[] data = hash.ComputeHash(message);
  string hex = BitConverter.ToString(data).Replace("-", string.Empty);
  return hex;
}

Python:

import hmac
import hashlib

hmac.new('secret', 'body', hashlib.sha256).hexdigest()

Ruby:

require 'openssl'

OpenSSL::HMAC.hexdigest('SHA256', 'secret', 'body')