Signature Algorithm

Last updated: 2020-07-02 17:06:40

    The signature algorithm v1 is simple and easy to use, but its functionality and security are not as good as the signature algorithm v3 which is therefore recommended.

    If you are using the signature algorithm for the first time, you are recommended to use the "signature string generation" feature in API Explorer and select "API 3.0 signature v1" as the signature version, which can generate a signature for demonstration and verification and provides signing examples for certain programming languages. Plus, it can also generate SDK code directly. Seven common open-source programming language SDKs are available for TencentCloud API, including Python, Java, PHP, Go, Node.js, .NET, and C++.

    TencentCloud API authenticates each access request, that is, each request must include signature information in the common request parameters to verify the identity of the requester.
    The signature is generated by the security credentials which consist of a SecretId and a SecretKey. If you do not have security credentials, go to the TencentCloud API Key page to apply for them; otherwise, you cannot call the TencentCloud API.

    1. Apply for security credentials

    Before using the TencentCloud API for the first time, go to the TencentCloud API Key page to apply for security credentials.
    Security credentials consist of a SecretId and a SecretKey:

    • SecretId is used to identify the API requester.
    • SecretKey is used to encrypt the string to sign that can be verified on the server.
    • You must keep your security credentials private and avoid disclosure.

    You can apply for security credentials as follows:

    1. Log in to the Tencent Cloud Console.
    2. Go to the TencentCloud API Key page.
    3. On the API Key Management page, click Create to create a SecretId/SecretKey pair.

    Note: each account can have up to two SecretId/SecretKey pairs.

    2. Generate a signature string

    With the SecretId and SecretKey, a signature can be generated. The following describes how to generate a signature:

    Suppose you have the following SecretId and SecretKey:

    • SecretId: AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE
    • SecretKey: Gu5t9xGARNpq86cd98joQYCN3EXAMPLE

    Note: this is just an example. To perform actual operations, use your own SecretId and SecretKey.

    For example, if you call the DescribeInstances API to query CVM instances, the request parameters may be as follows:

    Parameter Description Value
    Action Method DescribeInstances
    SecretId Key ID AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE
    Timestamp Current timestamp 1465185768
    Nonce Random positive integer 11886
    Region Instance region ap-guangzhou
    InstanceIds.0 ID of the instance to be queried ins-09dx96dg
    Offset Offset 0
    Limit Allowed maximum number of output entries 20
    Version API version number 2017-03-12

    2.1. Sort parameters

    Sort all the request parameters in an ascending lexicographical order (ASCII code) by their names. Note: (1) Parameters are sorted only by name but not by value. (2) The parameters are sorted based on ASCII code but not in an alphabetical order or by value. For example, InstanceIds.2 should be arranged behind InstanceIds.12. You can complete sorting by using a sorting function in a programming language, such as the ksort function in PHP. The parameters in the example are sorted as follows:

    {
        'Action' : 'DescribeInstances',
        'InstanceIds.0' : 'ins-09dx96dg',
        'Limit' : 20,
        'Nonce' : 11886,
        'Offset' : 0,
        'Region' : 'ap-guangzhou',
        'SecretId' : 'AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE',
        'Timestamp' : 1465185768,
        'Version': '2017-03-12',
    }

    When any other programming language is used for development and the parameters in the example are sorted, the same result as described above should be obtained.

    2.2. Concatenate a request string

    This step generates a request string.
    Format the request parameters sorted in the previous step into the form of parameter=value. For example, for the Action parameter, its parameter is Action and its value is DescribeInstances; therefore, the parameter will be formatted into Action=DescribeInstances.
    Note: the value is the original value instead of the URL-encoded value.

    Then, concatenate the formatted parameters with &. The generated request string will be as follows:

    Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Limit=20&Nonce=11886&Offset=0&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE&Timestamp=1465185768&Version=2017-03-12

    2.3. Generate an original signature string

    This step generates the original signature string.
    The original signature string consists of the following parameters:

    1. Request method: POST and GET methods are supported. GET is used here for the request. Please note that the method name should be in all capital letters.
    2. Request server: the domain name of the request for querying instances (DescribeInstances) is cvm.tencentcloudapi.com. The actual request domain name varies by the module to which the API belongs. For more information, please see the specific API document.
    3. Request path: the request path in the current version of TencentCloud API is fixed to /.
    4. Request string: the request string generated in the previous step.

    The rule for concatenating the original string of the signature is request method + request server + request path + ? + request string.

    The concatenation result in the example is as follows:

    GETcvm.tencentcloudapi.com/?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Limit=20&Nonce=11886&Offset=0&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE&Timestamp=1465185768&Version=2017-03-12

    2.4. Generate a signature string

    This step generates a signature string.
    Use the HMAC-SHA1 algorithm to sign the original signature string obtained in the previous step, and then Base64-encode the generated signature to get the final signature.

    The specific code when PHP is used is as follows:

    $secretKey = 'Gu5t9xGARNpq86cd98joQYCN3EXAMPLE';
    $srcStr = 'GETcvm.tencentcloudapi.com/?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Limit=20&Nonce=11886&Offset=0&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE&Timestamp=1465185768&Version=2017-03-12';
    $signStr = base64_encode(hash_hmac('sha1', $srcStr, $secretKey, true));
    echo $signStr;

    The obtained signature string is as follows:

    EliP9YW3pW28FpsEdkXt/+WcGeI=

    When any other programming language is used for development and the original signature in the example is verified, the same result as described above should be obtained.

    3. Encode a signature string

    The generated signature string cannot be directly used as a request parameter and needs to be URL-encoded.

    For example, if the signature string generated in the previous step is EliP9YW3pW28FpsEdkXt/+WcGeI=, the final value of the Signature request parameter will be EliP9YW3pW28FpsEdkXt%2f%2bWcGeI%3d, which will be used to generate the final request URL.

    Note: if you use the GET request method or use the POST request method with Content-Type of application/x-www-form-urlencoded, all the request parameter values must be URL-encoded (except the parameter key and the equal symbol (=)) before the request is sent. Non-ASCII characters must be encoded with UTF-8 before URL-encoding.

    Note: the network libraries of some programming languages automatically URL-encode all parameters. In this case, the signature string does not need to be URL-encoded again; otherwise, two rounds of URL-encoding will cause the signature to fail.

    Note: other parameter values also need to be encoded with RFC 3986. Use %XY in percent-encoding for special characters such as Chinese characters, where "X" and "Y" are hexadecimal characters (0–9 and uppercase A–F). Using lowercase characters will cause an error.

    4. Signature failure

    The following error codes may be returned for signature failure. Please resolve the errors accordingly.

    Error Code Error Description
    AuthFailure.SignatureExpire The signature expired.
    AuthFailure.SecretIdNotFound The key does not exist.
    AuthFailure.SignatureFailure Signature error.
    AuthFailure.TokenFailure Token error.
    AuthFailure.InvalidSecretId Invalid key (not TencentCloud API key type).

    5. Signature demo

    When calling TencentCloud API 3.0, you are recommended to use Tencent Cloud SDK 3.0 which encapsulates the signature process, enabling you to focus on only the specific APIs provided by the product during development. For more information, please visit the SDK Center. Currently, the following programming languages are supported:

    To further explain the signing process, specific programming languages are used as examples below to implement the process as described above. The request domain name, API, and parameter values in the above example are used here. The code below is for demonstration only. Please use the SDK for actual development.

    The final output URL might be: https://cvm.tencentcloudapi.com/?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Limit=20&Nonce=11886&Offset=0&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE&Signature=EliP9YW3pW28FpsEdkXt%2F%2BWcGeI%3D&Timestamp=1465185768&Version=2017-03-12.

    Note: the key in the example is not real, and the timestamp is not the current system time. If you open this URL in the browser or call it by using commands such as curl, an authentication error The signature expired will be returned. To obtain a URL that works, you need to replace the SecretId and SecretKey in this example with your own credentials and use the current system time as the Timestamp.

    Note: in the example below, even if you use the same programming language, the order of the parameters in the URL may be different in each execution. However, the order does not matter as long as all the parameters are included in the URL and the signature is calculated correctly.

    Note: the following code is only applicable to TencentCloud API 3.0. It cannot be directly used in other signature processes. Even with a legacy API, signature calculation errors may occur due to the differences in details. For more information, please see the corresponding documentation.

    Java

    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.util.Random;
    import java.util.TreeMap;
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import javax.xml.bind.DatatypeConverter;
    
    public class TencentCloudAPIDemo {
        private final static String CHARSET = "UTF-8";
    
        public static String sign(String s, String key, String method) throws Exception {
            Mac mac = Mac.getInstance(method);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(CHARSET), mac.getAlgorithm());
            mac.init(secretKeySpec);
            byte[] hash = mac.doFinal(s.getBytes(CHARSET));
            return DatatypeConverter.printBase64Binary(hash);
        }
    
        public static String getStringToSign(TreeMap<String, Object> params) {
            StringBuilder s2s = new StringBuilder("GETcvm.tencentcloudapi.com/?");
            // In the signing process, the parameters need to be sorted in lexicographical order. `TreeMap` is used here to guarantee the correct order
            for (String k : params.keySet()) {
                s2s.append(k).append("=").append(params.get(k).toString()).append("&");
            }
            return s2s.toString().substring(0, s2s.length() - 1);
        }
    
        public static String getUrl(TreeMap<String, Object> params) throws UnsupportedEncodingException {
            StringBuilder url = new StringBuilder("https://cvm.tencentcloudapi.com/?");
            // An actual request URL has no requirement for the order of parameters
            for (String k : params.keySet()) {
                // The request string needs to be URL-encoded. As the key consists of only English letters, only the value is URL-encoded
                url.append(k).append("=").append(URLEncoder.encode(params.get(k).toString(), CHARSET)).append("&");
            }
            return url.toString().substring(0, url.length() - 1);
        }
    
        public static void main(String[] args) throws Exception {
            TreeMap<String, Object> params = new TreeMap<String, Object>(); // TreeMap supports automatic sorting
            // A random number should be used during an actual call, such as `params.put("Nonce", new Random().nextInt(java.lang.Integer.MAX_VALUE));`
            params.put("Nonce", 11886); // Common parameter.
            // The current system time should be used during an actual call, such as `params.put("Timestamp", System.currentTimeMillis() / 1000);`
            params.put("Timestamp", 1465185768); // Common parameter
            params.put("SecretId", "AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE"); // Common parameter
            params.put("Action", "DescribeInstances"); // Common parameter
            params.put("Version", "2017-03-12"); // Common parameter
            params.put("Region", "ap-guangzhou"); // Common parameter
            params.put("Limit", 20); // Business parameter
            params.put("Offset", 0); // Business parameter
            params.put("InstanceIds.0", "ins-09dx96dg"); // Business parameter
            params.put("Signature", sign(getStringToSign(params), "Gu5t9xGARNpq86cd98joQYCN3EXAMPLE", "HmacSHA1")); // Common parameter
            System.out.println(getUrl(params));
        }
    }

    Python

    Note: in the Python 2 environment, the following requests dependency package must be installed first by running pip install requests.

    # -*- coding: utf8 -*-
    import base64
    import hashlib
    import hmac
    import time
    
    import requests
    
    secret_id = "AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE"
    secret_key = "Gu5t9xGARNpq86cd98joQYCN3EXAMPLE"
    
    def get_string_to_sign(method, endpoint, params):
        s = method + endpoint + "/?"
        query_str = "&".join("%s=%s" % (k, params[k]) for k in sorted(params))
        return s + query_str
    
    def sign_str(key, s, method):
        hmac_str = hmac.new(key.encode("utf8"), s.encode("utf8"), method).digest()
        return base64.b64encode(hmac_str)
    
    if __name__ == '__main__':
        endpoint = "cvm.tencentcloudapi.com"
        data = {
            'Action' : 'DescribeInstances',
            'InstanceIds.0' : 'ins-09dx96dg',
            'Limit' : 20,
            'Nonce' : 11886,
            'Offset' : 0,
            'Region' : 'ap-guangzhou',
            'SecretId' : secret_id,
            'Timestamp' : 1465185768, # int(time.time())
            'Version': '2017-03-12'
        }
        s = get_string_to_sign("GET", endpoint, data)
        data["Signature"] = sign_str(secret_key, s, hashlib.sha1)
        print(data["Signature"])
        # The API will be called actually, and fees may be incurred if the call is successful
        # resp = requests.get("https://" + endpoint, params=data)
        # print(resp.url)

    Go

    package main
    
    import (
        "bytes"
        "crypto/hmac"
        "crypto/sha1"
        "encoding/base64"
        "fmt"
        "sort"
    )
    
    func main() {
        secretId := "AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE"
        secretKey := "Gu5t9xGARNpq86cd98joQYCN3EXAMPLE"
        params := map[string]string{
            "Nonce":         "11886",
            "Timestamp":     "1465185768",
            "Region":        "ap-guangzhou",
            "SecretId":      secretId,
            "Version":       "2017-03-12",
            "Action":        "DescribeInstances",
            "InstanceIds.0": "ins-09dx96dg",
            "Limit":         "20",
            "Offset":        "0",
        }
    
        var buf bytes.Buffer
        buf.WriteString("GET")
        buf.WriteString("cvm.tencentcloudapi.com")
        buf.WriteString("/")
        buf.WriteString("?")
    
        // sort keys by ascii asc order
        keys := make([]string, 0, len(params))
        for k, _ := range params {
            keys = append(keys, k)
        }
        sort.Strings(keys)
    
        for i := range keys {
            k := keys[i]
            buf.WriteString(k)
            buf.WriteString("=")
            buf.WriteString(params[k])
            buf.WriteString("&")
        }
        buf.Truncate(buf.Len() - 1)
    
        hashed := hmac.New(sha1.New, []byte(secretKey))
        hashed.Write(buf.Bytes())
    
        fmt.Println(base64.StdEncoding.EncodeToString(hashed.Sum(nil)))
    }

    PHP

    <?php
    $secretId = "AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE";
    $secretKey = "Gu5t9xGARNpq86cd98joQYCN3EXAMPLE";
    $param["Nonce"] = 11886;//rand();
    $param["Timestamp"] = 1465185768;//time();
    $param["Region"] = "ap-guangzhou";
    $param["SecretId"] = $secretId;
    $param["Version"] = "2017-03-12";
    $param["Action"] = "DescribeInstances";
    $param["InstanceIds.0"] = "ins-09dx96dg";
    $param["Limit"] = 20;
    $param["Offset"] = 0;
    
    ksort($param);
    
    $signStr = "GETcvm.tencentcloudapi.com/?";
    foreach ( $param as $key => $value ) {
        $signStr = $signStr . $key . "=" . $value . "&";
    }
    $signStr = substr($signStr, 0, -1);
    
    $signature = base64_encode(hash_hmac("sha1", $signStr, $secretKey, true));
    echo $signature.PHP_EOL;
    // need to install and enable curl extension in php.ini
    // $param["Signature"] = $signature;
    // $url = "https://cvm.tencentcloudapi.com/?".http_build_query($param);
    // echo $url.PHP_EOL;
    // $ch = curl_init();
    // curl_setopt($ch, CURLOPT_URL, $url);
    // $output = curl_exec($ch);
    // curl_close($ch);
    // echo json_decode($output);

    Was this page helpful?

    Was this page helpful?

    • Not at all
    • Not very helpful
    • Somewhat helpful
    • Very helpful
    • Extremely helpful
    Send Feedback
    Help