Skip to main content

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)​

caution

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_key
  • timestamp
  • nonce
  • id (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);
}
}