Skip to content

Notification Signature

Notification Signature

Verify a notification signature

All notifications/callbacks to the merchant should be signed using the HMAC-SHA256 algorithm, and the contents of the signature should be included in the "Liquido-Signature" header. This header should have the signature timestamp in seconds and the hash function used, such as below:

algorithm=HmacSHA256,timestamp={{timestamp_in_seconds}},signature={{signature}}

A merchant can verify the signature with the following steps:

  • Get the payload as a raw request body string
  • Set the signature content as: payload={{payload}},timestamp={{current_timestamp_in_seconds}}
  • Set the signature secret to the client secret used in the OAuth Token
  • signature = HmacSHA256(content, secret)

Example of HMAC signature verification in Java

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.codec.binary.Hex;


public class HmacSignUtils {
    private static final String HEADER_FORMAT_STRING = "algorithm=%s,timestamp=%s,signature=%s";

    private static final String CONTENT_FORMAT_STRING = "payload=%s,timestamp=%s";

    public static final String ALGORITHM = "HmacSHA256";

    public static final String SIGNATURE_HEADER_KEY = "Liquido-Signature";

    public boolean verifySignature(
            final String signature, 
            final String payload, 
            final String timestamp,
            final String secret
    ) throws NoSuchAlgorithmException, InvalidKeyException {
        final String content = String.format(CONTENT_FORMAT_STRING, payload, timestamp);
        return signature.equals(calculateSignature(content, secret));
    }

    private static String calculateSignature(final String content, final String secret)
            throws NoSuchAlgorithmException, InvalidKeyException {
        final Mac sha256Hmac = Mac.getInstance(ALGORITHM);
        final SecretKeySpec keySpec =
                new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), ALGORITHM);
        sha256Hmac.init(keySpec);
        final byte[] digest = sha256Hmac.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return Hex.encodeHexString(digest);
    }

}
Back to top