Signature

Updated at:
Copy as MD

Every TSDB API request requires a signature for authentication, regardless of whether the request uses HTTP or HTTPS. The signature is computed from your AccessKey ID and AccessKey secret using HMAC-SHA1.

If you use an Alibaba Cloud SDK, the SDK handles request signing automatically. Read this page only if you are making direct API calls without an SDK or implementing a custom client.

How it works

Signing a request involves three high-level steps:

  1. Build a canonicalized query string from the sorted, URL-encoded request parameters.

  2. Construct a StringToSign from the HTTP method, a percent-encoded slash, and the encoded canonicalized query string.

  3. Compute an HMAC-SHA1 hash of StringToSign using your AccessKey secret, Base64-encode the result, and append it to the request as the Signature parameter.

TSDB then replicates this process on the server side and grants access only when the signatures match.

Prerequisites

Before you begin, ensure that you have:

  • An AccessKey ID and AccessKey secret — obtain and manage these on the Alibaba Cloud console

  • Familiarity with HMAC-SHA1 (RFC 2104) and Base64 encoding

Sign a request

Step 1: Build the canonicalized query string

1.1 Sort the parameters

Collect all public request parameters and your API-specific parameters. Sort them alphabetically by parameter name. Exclude the Signature parameter itself.

For GET requests, these parameters form the query string — the portion of the URI after ?, with pairs joined by &.

1.2 URL-encode the names and values

Encode each parameter name and value using UTF-8 percent-encoding. Apply these rules:

  • Leave unencoded: letters A–Z and a–z, digits 0–9, and the characters -, _, ., ~

  • Encode everything else as %XY, where XY is the uppercase hex value of the ASCII code — for example, " becomes %22

  • Encode extended UTF-8 characters as %XY%ZA…

  • Encode spaces as %20, not +

Important

Standard URL-encoding libraries such as Java's java.net.URLEncoder follow the application/x-www-form-urlencoded MIME type, which differs from the rules above. After encoding, replace + with %20, * with %2A, and change %7E back to ~.

1.3 Join each name–value pair with =

Connect each encoded parameter name to its encoded value with an equal sign.

1.4 Join all pairs with &

Sort the name=value pairs alphabetically, then join them with & to form the canonicalized query string.

Step 2: Construct the StringToSign

Use this format:

StringToSign =
  HTTPMethod + "&" +
  percentEncode("/") + "&" +
  percentEncode(CanonicalizedQueryString)
ComponentValue
HTTPMethodThe HTTP method for the request, for example GET
percentEncode("/")The percent-encoded slash — always %2F
percentEncode(CanonicalizedQueryString)The canonicalized query string from step 1, encoded again using the rules in step 1.2

Step 3: Compute the HMAC-SHA1 signature

Compute the HMAC value of StringToSign using RFC 2104 and SHA1. The signing key is your AccessKey secret followed by & (ASCII 38):

Key = AccessKey secret + "&"

Step 4: Base64-encode the HMAC value

Base64-encode the HMAC value from step 3. The result is your signature.

Step 5: Append the signature to the request

Add the signature as the Signature parameter. URL-encode the signature value per RFC 3986 before appending it, the same as any other parameter value.

Sample

This section walks through signing a DescribeHiTSDBInstanceList request. The output at each step lets you verify your own implementation against known values.

Starting parameters (before signing):

AccessKeyId=testid&Action=DescribeHiTSDBInstanceList&Format=JSON&RegionId=cn-hangzhou&SignatureMethod=HMAC-SHA1&SignatureNonce=ae5bdbeb-9b44-40a1-8bb4-b40784bff686&SignatureVersion=1.0&Timestamp=2016-01-20T14%3A26%3A15Z&Version=2017-06-01

StringToSign (after sorting, URL-encoding, and applying the formula from step 2):

GET&%2F&AccessKeyId%3Dtestid&Action%3DDescribeHiTSDBInstanceList&Format%3DJSON&RegionId%3Dcn-hangzhou&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3Dae5bdbeb-9b44-40a1-8bb4-b40784bff686&SignatureVersion%3D1.0&Timestamp%3D2016-01-20T14%253A26%253A15Z&Version%3D2017-06-01

HMAC-SHA1 key and computed signature:

ValueContent
AccessKey IDtestid
AccessKey secrettestsecret
HMAC keytestsecret&
Computed signatureh/ka/jNO+WZv8Tqgo4a75sp6eTs=

Final signed request URL (with Signature appended and URL-encoded):

http://hitsdb.aliyuncs.com/?AccessKeyId=testid&Action=DescribeHiTSDBInstanceList&Format=JSON&RegionId=cn-hangzhou&SignatureMethod=HMAC-SHA1&SignatureNonce=ae5bdbeb-9b44-40a1-8bb4-b40784bff686&SignatureVersion=1.0&Timestamp=2016-01-20T14%3A26%3A15Z&Version=2017-06-01&Signature=h%2Fka%2FjNO%2BWZv8Tqgo4a75sp6eTs%3D

Java sample code

The following Java example constructs and signs a DescribeHiTSDBInstanceList request. All signing steps described above correspond directly to the annotated sections in the code.

public static void hitsdbOpenAPI() throws NoSuchAlgorithmException, InvalidKeyException, IOException {
    // Step 1: Set credentials
    String accessKey = "testid";
    String accessSecret = "testsecret";

    // Step 1.1: Collect and sort parameters alphabetically using TreeMap
    Map<String, String> parameters = new TreeMap<String, String>();
    parameters.put("Format", "JSON");
    parameters.put("Action", "DescribeHiTSDBInstanceList");
    parameters.put("Version", "2017-06-01");
    parameters.put("AccessKeyId", accessKey);
    parameters.put("SignatureMethod", "HMAC-SHA1");
    parameters.put("Timestamp", getISO8601Time());
    parameters.put("SignatureVersion", "1.0");
    parameters.put("SignatureNonce", UUID.randomUUID().toString());
    parameters.put("RegionId", "cn-hangzhou");

    // Steps 1.2-1.4: URL-encode names and values, then join with = and &
    StringBuilder paramStr = new StringBuilder();
    for (Map.Entry<String, String> entry : parameters.entrySet()) {
        paramStr.append(percentEncode(entry.getKey()))
                .append("=")
                .append(percentEncode(entry.getValue()))
                .append("&");
    }
    paramStr.deleteCharAt(paramStr.length() - 1);

    // Step 2: Construct StringToSign
    StringBuilder stringToSign = new StringBuilder();
    stringToSign.append("GET").append("&")
                .append(percentEncode("/")).append("&")
                .append(percentEncode(paramStr.toString()));

    // Step 3: Compute HMAC-SHA1 - key is AccessKey secret + "&"
    Mac mac = Mac.getInstance("HmacSHA1");
    mac.init(new SecretKeySpec((accessSecret + "&").getBytes("UTF-8"), "HmacSHA1"));
    byte[] signData = mac.doFinal(stringToSign.toString().getBytes("UTF-8"));

    // Step 4: Base64-encode the HMAC value
    String signStr = Base64Helper.encode(signData);

    // Step 5: Append URL-encoded signature to the request URL
    String requestUrl = "http://hitsdb.aliyuncs.com/?" + paramStr.toString()
            + "&Signature=" + percentEncode(signStr);

    // Send the HTTP GET request
    URL url = new URL(requestUrl);
    HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
    httpConn.setRequestMethod("GET");
    httpConn.setDoOutput(true);
    httpConn.setDoInput(true);
    httpConn.setUseCaches(false);
    httpConn.connect();

    InputStream content = httpConn.getInputStream();
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    byte[] buff = new byte[1024];
    while (true) {
        final int read = content.read(buff);
        if (read == -1) break;
        outputStream.write(buff, 0, read);
    }
    System.out.println(new String(outputStream.toByteArray()));
}

// URL-encode a value according to the rules in step 1.2
public static String percentEncode(String value) throws UnsupportedEncodingException {
    return value != null ? URLEncoder.encode(value, "UTF-8")
            .replace("+", "%20")
            .replace("*", "%2A")
            .replace("%7E", "~") : null;
}

// Return the current time in ISO 8601 format (UTC)
static String getISO8601Time() {
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    df.setTimeZone(new SimpleTimeZone(0, "GMT"));
    return df.format(new Date());
}

Replace testid and testsecret with your actual AccessKey ID and AccessKey secret. Store credentials in environment variables rather than hardcoding them in source code.