Appearance
Signature Verification
The iGV platform uses HMAC-SHA256 to sign callback requests. Sellers should verify the signature to ensure request authenticity.
Constructing the Signature String
The signature string is formed by directly concatenating the following three parts (no separator):
raw_string = X-Timestamp + X-Request-Id + secretKey| Part | Source | Description |
|---|---|---|
| X-Timestamp | Request header | Value of the X-Timestamp header |
| X-Request-Id | Request header | Value of the X-Request-Id header |
secretKey | Platform-assigned | Key assigned by iGV (see Secret Key) |
Computing the Signature
Use the secretKey as the HMAC key and compute SHA256 on the raw_string:
expected_signature = HMAC-SHA256(raw_string, secretKey)Compare the computed result with the X-Signature value from the request header. If they match, the request is authentic.
Full Example
Given data:
X-Timestamp:1734850099000X-Request-Id:2002986662652579841secretKey:aBcDeFgHiJkLmNoPqRsTuVwXyZ012345
Step 1 — Concatenate the raw string:
17348500990002002986662652579841aBcDeFgHiJkLmNoPqRsTuVwXyZ012345Step 2 — Compute HMAC-SHA256: Using aBcDeFgHiJkLmNoPqRsTuVwXyZ012345 as the key, compute HMAC-SHA256 on the above raw string.
Step 3 — Compare: Compare the computed result with the X-Signature header value (case-insensitive).
Code Examples
Java
java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
public class CallbackSignatureVerifier {
public static boolean verify(String timestamp, String requestId,
String secretKey, String receivedSignature) throws Exception {
String rawString = timestamp + requestId + secretKey;
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(
secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
mac.init(keySpec);
byte[] hash = mac.doFinal(rawString.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
hexString.append(String.format("%02x", b));
}
return hexString.toString().equalsIgnoreCase(receivedSignature);
}
}Python
python
import hmac
import hashlib
def verify_signature(timestamp: str, request_id: str,
secret_key: str, received_signature: str) -> bool:
raw_string = timestamp + request_id + secret_key
expected = hmac.new(
secret_key.encode("utf-8"),
raw_string.encode("utf-8"),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected.lower(), received_signature.lower())Go
go
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"strings"
)
func verifySignature(timestamp, requestId, secretKey, receivedSignature string) bool {
rawString := timestamp + requestId + secretKey
mac := hmac.New(sha256.New, []byte(secretKey))
mac.Write([]byte(rawString))
expected := hex.EncodeToString(mac.Sum(nil))
return strings.EqualFold(expected, receivedSignature)
}Handling Verification Failures
If signature verification fails:
- Return a non-200 status code (recommended:
401or403) - Log the request for debugging
- Do not execute any business logic
Security Reminder
Never skip signature verification. Unverified requests may originate from malicious third parties.
