Skip to main content

Sample Code

PHP

  /**
   * check that the given API signature and timestamp are valid
   * @param string $signature calculated from public $key and timestamp
   * @param int $timestamp prevents reuse of an old signature
   * @param string $key public key given to each organisation
   * @return bool
   */
  public static function validate(string $signature, int $timestamp, string $key): bool
  {
      // check if the timestamp is within 5 mins of now to prevent reuse of stolen signature
      if (abs(time() - $timestamp) > 300) {
          return false;
      }

    // get your secret from a database or environment
      $apiSecret = ...

      // perform your own encoding
      $hmac = encode($key, $apiSecret $timestamp);

      // does it match the given signature?
      return hash_equals($hmac, $signature);
  }

  /**
   * create a signature by applying the secret to key+timestamp
   */
  public function encode(string $key, string $secret, int $timestamp): string
  {
      // hash using values provided
      return base64_encode(
          hash_hmac(
              'sha256',
              $key . $timestamp,
              $secret
          )
      );
  }

Java

public class WebhookSignatureValidator {
    public boolean validateSignature(String body,
                                     String signature,
                                     String secretKey,
                                     String timestamp) throws NoSuchAlgorithmException, InvalidKeyException {

        // Create the message to be signed by concatenating the message body and the timestamp
        var message = body + timestamp;

        // Initialize the MAC routine with the secret key
        var mac = Mac.getInstance("HmacSHA256");
        var secret = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        mac.init(secret);
        
        // Create a digest of the bytes in the message
        byte[] digest = mac.doFinal(message.getBytes());

        // Print the digest as lower-case hex characters
        var enc = DatatypeConverter.printHexBinary(digest).toLowerCase();
        
        return signature.equals(enc);
    }
}