#
Description
Callback signature verification can be used to validate the legitimacy of callback requests to the Sud server based on the signature (optional).
1. Preparation
Application ID (app_id), application secret (app_secret)
2. Construct the signature string
- 2.1 First, the server obtains the signature information from the callback request HTTP header.
- HTTP request header Sud-AppId: application ID
- HTTP request header Sud-Timestamp: callback timestamp
- HTTP request header Sud-Nonce: random string
- HTTP request header Sud-Signature: signature value
- 2.2 The signature string has a total of four lines, each corresponding to a parameter. The line ends with \n, including the last line.
Application ID\n
Callback timestamp\n
Random string\n
Request body\n
- 2.3 Signature string example:
1461564080052506636
146634788974
keVJLJTItd1VBtGT
{"app_id": "1461564080052506238","mg_id": "1461227817776713818","room_id": "9009","round_id": "ce56b6lzi1a7-cehorlmy01pq-ckmfkba10iv7","currency_amount": "2", "timestamp": 1654079242000}
3. Calculate the signature value and verify the signature
Use the application secret (app_secret) to encrypt the signature string with the HmacSHA1
algorithm to generate the corresponding signature value, and compare it with the value of the HTTP request header Sud-Signuture
.
Java example code:
/**
* Verify signature
*
* @param request Request body
* @param requestBody Request content. To ensure the consistency of data between the sender and receiver, it is recommended to take the corresponding value in the interceptor
* @return true: signature verification succeeded, false: signature verification failed
*/
public boolean verifySignature(HttpServletRequest request, String requestBody) {
// SudAppId
String sudAppId = request.getHeader("Sud-AppId");
// SudTimestamp
String sudTimestamp = request.getHeader("Sud-Timestamp");
// SudNonce
String sudNonce = request.getHeader("Sud-Nonce");
// SudSignature
String sudSignature = request.getHeader("Sud-Signature");
// Request body (to ensure the consistency of data between the sender and receiver, it is recommended to take the corresponding value in the interceptor)
String body = requestBody;
// Construct the signature string
String signContent = String.format("%s\n%s\n%s\n%s\n", sudAppId, sudTimestamp, sudNonce, body);
// Calculate the signature value
String appSecret = "";
HMac hMac = new HMac(HmacAlgorithm.HmacSHA1, appSecret.getBytes());
String signature = hMac.digestHex(signContent);
// Compare the signature value. true: signature verification succeeded, false: signature verification failed
return sudSignature.equals(signature);
}
Node example code:
const Crypto = require('crypto');
function verifySignature(request) {
// SudAppId
let sudAppId = request.headers["Sud-AppId"];
// SudTimestamp
let sudTimestamp = request.headers["Sud-Timestamp"];
// SudNonce
let sudNonce = request.headers["Sud-Nonce"];
// SudSignature
let sudSignature = request.headers["Sud-Signature"];
// Request body (to ensure the consistency of data between the sender and receiver, it is recommended to take the corresponding value in the interceptor)
let body = request.body;
// Construct the signature string
let signContent := sudAppId + '\n' + sudTimestamp + '\n' + sudNonce + '\n' + JSON.stringify(body) + '\n';
// Calculate the signature value
let appSecret = '';
let hmac = Crypto.createHmac('sha1', appSecret);
let signature = hmac.update(signContent).digest('hex');
// Compare the signature value. true: signature verification succeeded, false: signature verification failed
return sudSignature == signature;
}
Go example code:
import (
"crypto/hmac"
"crypto/sha1"
"fmt"
"github.com/valyala/fasthttp"
)
func verifySignature(ctx *fasthttp.RequestCtx) bool {
// SudAppId
sudAppId := ctx.Request.Header.Peek("Sud-AppId")
// SudTimestamp
sudTimestamp := ctx.Request.Header.Peek("Sud-Timestamp")
// SudNonce
sudNonce := ctx.Request.Header.Peek("Sud-Nonce")
// SudSignature
sudSignature := ctx.Request.Header.Peek("Sud-Signature")
// Request body (to ensure the consistency of data between the sender and receiver, it is recommended to take the corresponding value in the interceptor)
body := ctx.Request.Body()
// Construct the signature string
signContent := fmt.Sprintf("%s\n%s\n%s\n%s\n", sudAppId, sudTimestamp, sudNonce, string(body))
// Calculate the signature value
appSecret := ""
mac := hmac.New(sha1.New, []byte(appSecret))
mac.Write([]byte(signContent))
signature := hex.EncodeToString(mac.Sum(nil))
// Compare the signature value. true: signature verification succeeded, false: signature verification failed
return sudSignature == signature
}