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')