Verify signature
Setu will sign every notification sent to your webhook endpoint by generating a signature and sending it in a custom header x-setu-signature.
This signature helps you to verify that the notifications were sent by Setu rather than a third party
Generating the signature
Setu generates a signature using the Hash-based Message Authentication Code (HMAC). An HMAC is generated using a secret key in combination with a cryptographic hash function, SHA256.
This HMAC becomes the signature of the webhook, which is then used to authenticate the webhook and verify its payload.
You need to create a unique secret key for your webhook endpoint and this is shared between both the webhook producer (Setu) and consumer (you).
This secret usually is a alpha-numeric string and its length can vary between 20 to 50 characters. You can use this page to generate a unique secret.
Verify the signature
To verify a signature, you need to extract the notifcation payload and the x-setu-signature header from the request received on your webhook endpoint.
Below are the code snippets for verification:
Please ensure the notification payload is a string when using the below snippets
const crypto = require('crypto');
// Generate HMAC SHA-256 signature
function generateHMACSHA256(message, secret) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(message);
return hmac.digest('base64');
}
// Verify HMAC SHA-256 signature
function verifyHMACSHA256(message, secret, signature) {
const expectedSignature = generateHMACSHA256(message, secret);
return crypto.timingSafeEqual(Buffer.from(signature, 'base64'), Buffer.from(expectedSignature, 'base64'));
}
const message = '{"id":"01J1ZBPW7Y8M6NV1YXJYGJST5Q","rrn":"418666712574"}';
const secret = "thisisasecretkey";
const signature = "x-setu-signature value"
const isValid = verifyHMACSHA256(message, secret, signature);
console.log("Is the signature valid?", isValid);import base64
import hashlib
import hmac
def generate_hmac_sha256(message, secret):
"""
Generate HMAC SHA-256 signature for a given message and secret
"""
secret_bytes = secret.encode('utf-8')
message_bytes = message.encode('utf-8')
hmac_instance = hmac.new(secret_bytes, message_bytes, hashlib.sha256)
signature = base64.b64encode(hmac_instance.digest()).decode('utf-8')
return signature
def verify_hmac_sha256(message, secret, signature):
"""
Verify HMAC SHA-256 signature for a given message and secret
"""
expected_signature = generate_hmac_sha256(message, secret)
return hmac.compare_digest(signature, expected_signature)
message = '{"id":"01J1ZBPW7Y8M6NV1YXJYGJST5Q","rrn":"418666712574"}'
secret = "thisisasecretkey"
signature = "x-setu-signature value"
is_valid = verify_hmac_sha256(message, secret, signature)
print("Is the signature valid?", is_valid)import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class Main {
// Generate HMAC SHA-256 signature
public static String generateHMACSHA256(String message, String secret) throws Exception {
Mac sha256Hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
sha256Hmac.init(secretKey);
byte[] signedBytes = sha256Hmac.doFinal(message.getBytes());
return Base64.getEncoder().encodeToString(signedBytes);
}
// Verify HMAC SHA-256 signature
public static boolean verifyHMACSHA256(String message, String secret, String signature) throws Exception {
String expectedSignature = generateHMACSHA256(message, secret);
return signature.equals(expectedSignature);
}
public static void main(String[] args) {
try {
String message = "{\"id\":\"01J1ZBPW7Y8M6NV1YXJYGJST5Q\",\"rrn\":\"418666712574\"}";
String secret = "thisisasecretkey";
String signature = "x-setu-signature value";
boolean isValid = verifyHMACSHA256(message, secret, signature);
System.out.println("Is the signature valid? " + isValid);
} catch (Exception e) {
e.printStackTrace();
}
}
}package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
)
// GenerateHMACSHA256 generates an HMAC SHA-256 signature for a given message and secret
func generateHMACSHA256(message, secret string) string {
key := []byte(secret)
h := hmac.New(sha256.New, key)
h.Write([]byte(message))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// VerifyHMACSHA256 verifies an HMAC SHA-256 signature for a given message and secret
func verifyHMACSHA256(message, secret, signature string) bool {
key := []byte(secret)
h := hmac.New(sha256.New, key)
h.Write([]byte(message))
expectedSignature := base64.StdEncoding.EncodeToString(h.Sum(nil))
return hmac.Equal([]byte(signature), []byte(expectedSignature))
}
func main() {
message :='{"id":"01J1ZBPW7Y8M6NV1YXJYGJST5Q","rrn":"418666712574"}'
secret := "thisisasecretkey"
signature := "x-setu-signature value"
isValid := verifyHMACSHA256(message, secret, signature)
fmt.Println("Is the signature valid?", isValid)
}