Here are sample snippets to help you implement signature verification:
from base64 import b64decodeimport binasciifrom cryptography.hazmat.primitives import serializationfrom cryptography.hazmat.primitives.asymmetric import ed25519# load public key from filesystem, you may adapt depending on your secret management frameworkpublic_key = serialization.load_pem_public_key(open("/var/secrets/partoo.pub.pem"))def validate_signature(request): if (signature:=request.headers.get("X-Partoo-Signature-v1")) is None: raise ValueError("Missing signature") # don't trust your inputs # will raise a subclass of ValueError if format is invalid decoded_signature = b64decode(signature, validate=True) # validate payload's signature try: public_key.verify(decoded_signature, request.body.encode()) except Exception as e: raise ValueError("Invalid signature") from e
const fs = require('fs');const crypto = require('crypto');// Load public key from filesystemconst publicKey = fs.readFileSync('/var/secrets/partoo.pub.pem', 'utf8');function validateSignature(request) { const signature = request.headers['x-partoo-signature-v1']; if (!signature) { throw new Error('Missing signature'); } // Decode the base64 signature let decodedSignature; try { decodedSignature = Buffer.from(signature, 'base64'); } catch (err) { throw new Error('Invalid signature format'); } // Verify the payload's signature const payload = request.body; if (!crypto.verify(null, Buffer.from(payload), publicKey, decodedSignature)) { throw new Error('Invalid signature'); }}
import java.io.IOException;import java.nio.file.Files;import java.nio.file.Paths;import java.security.KeyFactory;import java.security.PublicKey;import java.security.Signature;import java.security.spec.X509EncodedKeySpec;import java.util.Base64;public class WebhookValidator { private static PublicKey loadPublicKey(String path) throws Exception { String keyPem = new String(Files.readAllBytes(Paths.get(path))); keyPem = keyPem.replace("-----BEGIN PUBLIC KEY-----", "") .replace("-----END PUBLIC KEY-----", "") .replaceAll("\\s", ""); byte[] keyBytes = Base64.getDecoder().decode(keyPem); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("Ed25519"); return keyFactory.generatePublic(spec); } public static void validateSignature(String signatureHeader, String payload) throws Exception { if (signatureHeader == null || signatureHeader.isEmpty()) { throw new IllegalArgumentException("Missing signature"); } // Decode base64 signature byte[] decodedSignature; try { decodedSignature = Base64.getDecoder().decode(signatureHeader); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Invalid signature format", e); } // Load public key PublicKey publicKey = loadPublicKey("/var/secrets/partoo.pub.pem"); // Verify signature Signature sig = Signature.getInstance("Ed25519"); sig.initVerify(publicKey); sig.update(payload.getBytes()); if (!sig.verify(decodedSignature)) { throw new SecurityException("Invalid signature"); } }}
<?phpfunction validateSignature($request, $payload) { $signature = $request->header('X-Partoo-Signature-v1'); if (!$signature) { throw new Exception('Missing signature'); } // Decode base64 signature $decodedSignature = base64_decode($signature, true); if ($decodedSignature === false) { throw new Exception('Invalid signature format'); } // Load public key from filesystem $publicKeyPem = file_get_contents('/var/secrets/partoo.pub.pem'); $publicKey = openssl_pkey_get_public($publicKeyPem); if (!$publicKey) { throw new Exception('Failed to load public key'); } // Verify signature using Ed25519 $keyDetails = openssl_pkey_get_details($publicKey); $publicKeyRaw = $keyDetails['key']; // For Ed25519 verification with PHP, you may need sodium extension if (!function_exists('sodium_crypto_sign_verify_detached')) { throw new Exception('Sodium extension required for Ed25519 verification'); } // Extract raw public key (skip ASN.1 header) $rawKey = substr(base64_decode( str_replace(['-----BEGIN PUBLIC KEY-----', '-----END PUBLIC KEY-----', "\n"], '', $publicKeyPem) ), 12); if (!sodium_crypto_sign_verify_detached($decodedSignature, $payload, $rawKey)) { throw new Exception('Invalid signature'); }}?>