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:
Go to Profile Settings: Profile Settings
Locate the Personal Secret Section: Find the section labeled "Personal Secret."
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.
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.
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.")
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();
}
}
}
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.";
}
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.