Generate Signature
This section describes how to generate the signature required by the Dubbing SDK for authentication.
Important: Signature generation must be performed on your server, never on the client, to avoid leaking the secretKey.
1. Preparation: Keys (accessKey / secretKey)
Please contact us to obtain the keys required to integrate and launch your project.
The Dubbing SDK uses paired keys:
- accessKey — Works like an account identifier. It will be transmitted.
- secretKey — Works like a password. Never expose or transmit it to clients.
Your server must provide a signature-generation endpoint.
Clients request the signature → server generates it → server returns it to clients.
If the secretKey is compromised, the administrator must replace the key immediately.
2. Build the Signature String
The signature string consists of three lines, each ending with a newline (\n):
timestamp
nonce
userId
Step 1 — Generate timestamp
Current Unix timestamp in seconds.
Example command:
date +%s
Example value:
1676546987
Step 2 — Generate a random nonce
The nonce should be a random string. Example:
hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random
Example output:
1E7889295850730393A955964821CAF6
Step 3 — User ID
Example: 518
Step 4 — Combine to form signature string:
1676546987
1E7889295850730393A955964821CAF6
518
3. Compute Signature Value
Use HMAC-SHA1 with your secretKey, then Base64-URL encode the result.
Example signature:
B3W62RX1D4uJCJlRCX_SFuMevrw=
4. Construct Final Signature Token
Format:
key="value",key="value",...
Fields:
access_keytimestampnonceid(userId)signature
Example:
access_key="abcde",timestamp="1676546987",nonce="1E7889295850730393A955964821CAF6",id="518",signature="B3W62RX1D4uJCJlRCX_SFuMevrw="
5. Server-Side Example Code (Java)
package org.example;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;
public class DubbingTokenDemo {
public static void main(String[] args) {
long time = getTimestamp();
String nonce = buildNonce();
String userId = "518";
String data = buildData(time, nonce, userId);
String signature = encrypt(data, secretKey);
String token = buildToken(accessKey, time, nonce, userId, signature);
System.out.println(signature);
System.out.println(token);
}
public static final String HMAC_SHA1 = "HmacSHA1";
public static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final SecureRandom RANDOM = new SecureRandom();
public static final String secretKey = "123456";
public static final String accessKey = "abcde";
public static String buildNonce() {
char[] nonceChars = new char[16];
for (int index = 0; index < nonceChars.length; ++index) {
nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
}
return new String(nonceChars);
}
public static long getTimestamp() {
return System.currentTimeMillis() / 1000;
}
public static String buildData(long timestamp, String randomStr, String userId) {
return timestamp + "\n" + randomStr + "\n" + userId + "\n";
}
private static String encrypt(String data, String key) {
SecretKeySpec secret = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), HMAC_SHA1);
try {
Mac mac = Mac.getInstance(HMAC_SHA1);
mac.init(secret);
return Base64.getUrlEncoder().encodeToString(mac.doFinal(data.getBytes()));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("HMAC_SHA1 is not supported in the current Java environment", e);
} catch (InvalidKeyException e) {
throw new RuntimeException("Invalid secret key", e);
}
}
public static String buildToken(String accessKey, long timestamp, String nonce, String userId, String signature) {
String tokenStr = "access_key=\"%s\",timestamp=\"%s\",nonce=\"%s\",id=\"%s\",signature=\"%s\"";
return String.format(tokenStr, accessKey, timestamp, nonce, userId, signature);
}
}