Skip to content

Securing Webhooks

Overview

To ensure the authenticity and integrity of webhooks, we provide an X-Signature header that can be validated. This header contains a signature generated using your personal_secret, which you can verify to confirm that the webhook request is legitimate and has not been tampered with.

Important Notes

  • Setting a Personal Secret: If you do not have a personal secret set, please be aware that adding one will enable the X-Signature header on all outgoing webhooks. Ensure your server can accept and verify this header.

  • Renewing Your Personal Secret: If you already have a personal secret and choose to change it, the new secret will take immediate effect on webhook notifications. Ensure that your server is updated to use the new secret to avoid any disruptions.

Setting the Personal Secret

You can set or regenerate your personal secret by navigating to your profile settings on our platform. Follow these steps:

  1. Go to Profile Settings: Profile Settings

  2. Locate the Personal Secret Section: Find the section labeled "Personal Secret."

  3. Set or Regenerate the Secret:

    • If no secret is set, click "Set Personal Secret" to generate a new secret.
    • If a secret is already present, click "Regenerate Secret" to create a new one.

    Personal Secret

How the X-Signature Header is Built

Extract the txid from the Payload:

The txid (transaction ID) is a unique identifier included in the webhook payload. This ID is used as part of the signature generation process. Combine txid with a Personal Secret:

The personal secret is a shared secret key known only to the sender (e.g., the webhook provider) and the receiver (your application). This secret key is used to ensure that the signature can only be generated and verified by parties who know the secret. Generate HMAC (Hash-based Message Authentication Code):

HMAC is a specific type of message authentication code (MAC) that involves a cryptographic hash function and a secret key. In this case, the txid and the personal secret are used to generate the HMAC. The HMAC is typically generated using a hashing algorithm like SHA-256.

Verifying the X-Signature Header

When you receive a webhook, it’s essential to verify the X-Signature header to ensure the request is from a trusted source. Below are examples of how to perform this verification in Python, Java, PHP, and JavaScript.

python

import hmac
import hashlib
import base64

def verify_signature(txid, received_signature, personal_secret):
    # Generate the expected signature
    expected_signature = base64.b64encode(hmac.new(
        personal_secret.encode(),
        txid.encode(),
        hashlib.sha256
    ).digest()).decode()

    # Compare the expected signature with the received signature
    return hmac.compare_digest(expected_signature, received_signature)

# Example usage
txid = 'your_txid_here'
received_signature = 'received_signature_here'
personal_secret = 'your_personal_secret_here'

if verify_signature(txid, received_signature, personal_secret):
    print("Signature is valid.")
else:
    print("Invalid signature.")
java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class SignatureVerifier {
    public static boolean verifySignature(String txid, String receivedSignature, String personalSecret) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(personalSecret.getBytes(), "HmacSHA256");
        mac.init(secretKeySpec);

        byte[] signatureBytes = mac.doFinal(txid.getBytes());
        String expectedSignature = Base64.getEncoder().encodeToString(signatureBytes);

        return expectedSignature.equals(receivedSignature);
    }

    public static void main(String[] args) {
        try {
            String txid = "your_txid_here";
            String receivedSignature = "received_signature_here";
            String personalSecret = "your_personal_secret_here";

            if (verifySignature(txid, receivedSignature, personalSecret)) {
                System.out.println("Signature is valid.");
            } else {
                System.out.println("Invalid signature.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
php
function verifySignature($txid, $receivedSignature, $personalSecret) {
    // Generate the expected signature
    $expectedSignature = base64_encode(hash_hmac('sha256', $txid, $personalSecret, true));

    // Compare the expected signature with the received signature
    return hash_equals($expectedSignature, $receivedSignature);
}

// Example usage
$txid = 'your_txid_here';
$receivedSignature = 'received_signature_here';
$personalSecret = 'your_personal_secret_here';

if (verifySignature($txid, $receivedSignature, $personalSecret)) {
    echo "Signature is valid.";
} else {
    echo "Invalid signature.";
}
javascript
const crypto = require('crypto');

function verifySignature(txid, receivedSignature, personalSecret) {
    // Generate the expected signature
    const expectedSignature = crypto
        .createHmac('sha256', personalSecret)
        .update(txid)
        .digest('base64');

    // Compare the expected signature with the received signature
    return crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(receivedSignature));
}

// Example usage
const txid = 'your_txid_here';
const receivedSignature = 'received_signature_here';
const personalSecret = 'your_personal_secret_here';

if (verifySignature(txid, receivedSignature, personalSecret)) {
    console.log("Signature is valid.");
} else {
    console.log("Invalid signature.");
}

Conclusion

With the ability to manage your personal_secret, you have enhanced control over your webhook security. Always ensure that your server’s webhook handler is updated whenever you change the personal_secret to prevent any disruptions in service. If you have any questions or issues, please contact support.