Request Signature

Last updated: 2020-08-27 17:16:22

    Note:

    1. This document is only for the COS XML version.
    2. It does not apply to POST Object requests over HTTP.

    Overview

    RESTful APIs support anonymous and signed HTTP requests, which help you use COS resources. For a signed request, the COS server will authenticate its initiator.

    • Anonymous request: an HTTP request that does not contain any authentication information and is sent by using RESTful API.
    • Signed request: a request that is signed with authentication information. The COS server authenticates the requester of the signed request and only executes the authenticated ones; otherwise, it returns an error message and denies the request.

    The COS server performs HMAC (Hash Message Authentication Code) authentication schema.

    Besides, pre-signed URLs are provided in all language-specific SDKs so that you can easily access signed URLs and process requests. For more information, please see Pre-signed URL in applicable language-specific SDK documentation.

    Signature Use Cases

    In use cases where COS objects need to be published to the public, public read/private write is usually configured. It means that every one can read, but only accounts you specify with ACL policies can write to your objects. In this case, you can use ACL policies together with API request signature to authenticate access and control operation permission and period.

    Note:

    The API request signature described in this document is already included in the SDK. You need to follow the steps below only if you want to redevelop based on the initial APIs.

    In this case, multiple layers of security protection can be included for API requests:

    1. Requester authentication: verifies the identity of the requester by their unique ID and key.
    2. Transferred data anti-tampering: signs and verifies the data to ensure its integrity during transfer.
    3. Signature anti-theft: expires signatures to prevent them from being stolen for repeated use.

    Preparations

    1. APPID, SecretId, and SecretKey.
      They can be obtained on the API Key Management page in the CAM Console.
    2. Programming language:
      Supported programming languages include but are not limited to Java, PHP, .NET, C++, Node.js, and Python. You should determine the corresponding HMAC-SHA1, SHA1, and UrlEncode functions for the chosen language.
      The HMAC-SHA1 and SHA1 functions input UTF-8 encoded strings and output lowercase hexadecimal strings. The UrlEncode function works based on UTF-8 encoding. The following printable special characters in the ASCII range should also be encoded:
    Character Decimal Hex Character Decimal Hex
    (Space) 32 20 ; 59 3B
    ! 33 21 < 60 3C
    " 34 22 = 61 3D
    # 35 23 > 62 3E
    $ 36 24 ? 63 3F
    % 37 25 @ 64 40
    & 38 26 [ 91 5B
    ' 39 27 \ 92 5C
    ( 40 28 ] 93 5D
    ) 41 29 ^ 94 5E
    * 42 2A ` 96 60
    + 43 2B { 123 7B
    , 44 2C | 124 7C
    / 47 2F } 125 7D
    : 58 3A

    Generating Signature

    Step 1. Generate KeyTime

    1. Get the Unix timestamp StartTimestamp for the current time, which is the total number of seconds starting from January 1, 1970, 00:00:00 UTC (January 1, 1970, 08:00:00 Beijing time).
    2. Calculate the Unix timestamp EndTimestamp for the moment the signature will expire based on the timestamp above and the expected valid duration of the signature.
    3. Get the signature validity period (i.e., KeyTime) by splicing the two timestamps above in the format of StartTimestamp;EndTimestamp, such as 1557902800;1557910000.

    Step 2. Generate SignKey

    Calculate the message digest (hash value in hexadecimal lowercase) by using HMAC-SHA1 with SecretKey as the key and KeyTime as the message, which is SignKey, such as eb2519b498b02ac213cb1f3d1a3d27a3b3c9bc5f.

    Step 3. Generate UrlParamList and HttpParameters

    1. Traverse the HTTP request parameters to generate a key-to-value mapping Map and key list KeyList:
      • Encode keys by using UrlEncode and convert them to lowercase.
      • Encode values by using UrlEncode. In parameters without value, the value is considered to be an empty string. For example, the request path /?acl is considered as /?acl=.

        Note:

        The parameters in an HTTP request are what comes after ? in the request path. For example, in the request path /?versions&prefix=example-folder%2F&delimiter=%2F&max-keys=10, the request parameters are versions&prefix=example-folder%2F&delimiter=%2F&max-keys=10.

    2. Sort the KeyList in lexicographical order.
    3. Splice all key-value pairs in the Map in the order of the KeyList in the format of key1=value1&key2=value2&key3=value3, which is the HttpParameters.
    4. Splice all keys in the order of the KeyList in the format of key1;key2;key3, which is the UrlParamList.

    Samples

    • Sample 1:
      Request path: /?prefix=example-folder%2F&delimiter=%2F&max-keys=10
      UrlParamList: delimiter;max-keys;prefix
      HttpParameters: delimiter=%2F&max-keys=10&prefix=example-folder%2F

      Note:

      The request parameters in the request path are URL-encoded too when the request is actually sent; therefore, be careful not to repeat the URL-encoding.

    • Sample 2:
      Request path: /exampleobject?acl
      UrlParamList: acl
      HttpParameters: acl=

    Step 4. Generate HeaderList and HttpHeaders

    1. Traverse the HTTP request parameters and generate the key-to-value mapping Map and the key list KeyList, where keys are URL-encoded and converted to lowercase and values are URL-encoded.
    2. Sort the KeyList in lexicographical order.
    3. Splice all key-value pairs in the Map in the order of the KeyList in the format of key1=value1&key2=value2&key3=value3, which is the HttpHeaders.
    4. Splice all keys in the order of the KeyList in the format of key1;key2;key3, which is the HeaderList.

    Samples

    Request headers:

    Host: examplebucket-1250000000.cos.ap-shanghai.myqcloud.com
    Date: Thu, 16 May 2019 03:15:06 GMT
    x-cos-acl: private
    x-cos-grant-read: uin="100000000011"

    Calculate and get:

    • HeaderList = date;host;x-cos-acl;x-cos-grant-read
    • HttpHeaders = date=Thu%2C%2016%20May%202019%2003%3A15%3A06%20GMT&host=examplebucket-1250000000.cos.ap-shanghai.myqcloud.com&x-cos-acl=private&x-cos-grant-read=uin%3D%22100000000011%22

    Step 5. Generate HttpString

    Generate the HttpString based on the HTTP method, HTTP request path, HttpParameters, and HttpHeaders in the format of HttpMethod\nUriPathname\nHttpParameters\nHttpHeaders\n.

    Here:

    • HttpMethod is converted to lowercase, such as get or put.
    • UriPathname is the request path, such as / or /exampleobject.
    • \n is a line break. The two line breaks (if any) bookending an empty string should be retained, such as in get\n/exampleobject\n\n\n.

    Step 6. Generate StringToSign

    Generate the StringToSign based on the KeyTime and HttpString in the format of sha1\nKeyTime\nSHA1(HttpString)\n.
    Here:

    • sha1 is a fixed string.
    • \n is a line break.
    • SHA1(HttpString) is the message digest generated by calculating the HttpString with SHA1, which is in hexadecimal lowercase, such as 54ecfe22f59d3514fdc764b87a32d8133ea611e6.

    Step 7. Generate Signature

    Calculate the message digest by using HMAC-SHA1 with SignKey (in string form instead of original binary form) as the key and StringToSign as the message, which is Signature, such as 01681b8c9d798a678e43b685a9f1bba0f6c0e012.

    Step 8. Generate an actual signature

    Generate the actual signature based on SecretId, KeyTime, HeaderList, UrlParamList, and Signature in the following format:

    q-sign-algorithm=sha1
    &q-ak=SecretId
    &q-sign-time=KeyTime
    &q-key-time=KeyTime
    &q-header-list=HeaderList
    &q-url-param-list=UrlParamList
    &q-signature=Signature

    Note:

    Line breaks in the sample above are for easy understanding only and are not included in a real signature.

    Using Signature

    Signed HTTP requests initiated to COS through RESTful APIs can pass the signature in the following ways:

    1. Pass through a standard HTTP Authorization header, such as Authorization: q-sign-algorithm=sha1&q-ak=...&q-sign-time=1557989753;1557996953&...&q-signature=...
    2. Pass as an HTTP request parameter (be sure to URL-encode it), such as /exampleobject?q-sign-algorithm=sha1&q-ak=...&q-sign-time=1557989753%3B1557996953&...&q-signature=...

    Note:

    In the sample above, ... is used to substitute the specific signing information.

    Using Temporary Security Credentials (Temporary Key)

    If temporary security credentials are used when the signature is calculated, then the security token field x-cos-security-token should also be passed in when the request is sent. The method to pass in this field varies by how the signature is used:

    1. If the signature is passed in through the standard HTTP Authorization header, the security token field should be passed in through the x-cos-security-token request header at the same time, such as:
      Authorization: q-sign-algorithm=sha1&q-ak=...&q-sign-time=1557989753;1557996953&...&q-signature=...
      x-cos-security-token: ...
    2. If the signature is passed in through HTTP request parameters, the security token field should be passed in through the x-cos-security-token request parameter at the same time, such as:
      /exampleobject?q-sign-algorithm=sha1&q-ak=...&q-sign-time=1557989753%3B1557996953&...&q-signature=...&x-cos-security-token=...

    Note:

    In the example above, ... is used to substitute the specific signature and security token content.

    Sample Code

    Pseudocode

    KeyTime = [Now];[Expires]
    SignKey = HMAC-SHA1([SecretKey], KeyTime)
    HttpString = [HttpMethod]\n[HttpURI]\n[HttpParameters]\n[HttpHeaders]\n
    StringToSign = sha1\nKeyTime\nSHA1(HttpString)\n
    Signature = HMAC-SHA1(SignKey, StringToSign)

    Sample message digest calculation

    The samples below illustrate how to call HMAC-SHA1 in different languages:

    PHP

    $sha1HttpString = sha1('ExampleHttpString');
    
    $signKey = hash_hmac('sha1', 'ExampleKeyTime', 'YourSecretKey');

    Java

    import org.apache.commons.codec.digest.DigestUtils;
    import org.apache.commons.codec.digest.HmacUtils;
    
    String sha1HttpString = DigestUtils.sha1Hex("ExampleHttpString");
    
    String signKey = HmacUtils.hmacSha1Hex("YourSecretKey", "ExampleKeyTime");

    Python

    import hmac
    import hashlib
    
    sha1_http_string = hashlib.sha1('ExampleHttpString'.encode('utf-8')).hexdigest()
    
    sign_key = hmac.new('YourSecretKey'.encode('utf-8'), 'ExampleKeyTime'.encode('utf-8'), hashlib.sha1).hexdigest()

    Node.js

    var crypto = require('crypto');
    
    var sha1HttpString = crypto.createHash('sha1').update('ExampleHttpString').digest('hex');
    var signKey = crypto.createHmac('sha1', 'YourSecretKey').update('ExampleKeyTime').digest('hex');

    Go

    import (
        "crypto/hmac"
        "crypto/sha1"
    )
    
    h := sha1.New()
    h.Write([]byte("ExampleHttpString"))
    sha1HttpString := h.Sum(nil)
    
    var hashFunc = sha1.New
    h = hmac.New(hashFunc, []byte("YourSecretKey"))
    h.Write([]byte("ExampleKeyTime"))
    signKey := h.Sum(nil)

    Use Cases

    Preparations

    Log in to the API Key Management page in the CAM Console to get your APPID, SecretId, and SecretKey. Below is an example:

    APPID SecretId SecretKey
    1250000000 AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q BQYIM75p8x0iWVFSIgqEKwFprpRSVHlz

    Uploading object

    Original request

    PUT /exampleobject(%E8%85%BE%E8%AE%AF%E4%BA%91) HTTP/1.1
    Date: Thu, 16 May 2019 06:45:51 GMT
    Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com
    Content-Type: text/plain
    Content-Length: 13
    Content-MD5: mQ/fVh815F3k6TAUm8m0eg==
    x-cos-acl: private
    x-cos-grant-read: uin="100000000011"
    
    ObjectContent

    Intermediate variables

    • KeyTime = 1557989151;1557996351
    • SignKey = eb2519b498b02ac213cb1f3d1a3d27a3b3c9bc5f
    • UrlParamList = (empty string)
    • HttpParameters = (empty string)
    • HeaderList = content-length;content-md5;content-type;date;host;x-cos-acl;x-cos-grant-read
    • HttpHeaders = content-length=13&content-md5=mQ%2FfVh815F3k6TAUm8m0eg%3D%3D&content-type=text%2Fplain&date=Thu%2C%2016%20May%202019%2006%3A45%3A51%20GMT&host=examplebucket-1250000000.cos.ap-beijing.myqcloud.com&x-cos-acl=private&x-cos-grant-read=uin%3D%22100000000011%22
    • HttpString = put\n/exampleobject(tencentcloud)\n\ncontent-length=13&content-md5=mQ%2FfVh815F3k6TAUm8m0eg%3D%3D&content-type=text%2Fplain&date=Thu%2C%2016%20May%202019%2006%3A45%3A51%20GMT&host=examplebucket-1250000000.cos.ap-beijing.myqcloud.com&x-cos-acl=private&x-cos-grant-read=uin%3D%22100000000011%22\n
    • StringToSign = sha1\n1557989151;1557996351\n8b2751e77f43a0995d6e9eb9477f4b685cca4172\n
    • Signature = 3b8851a11a569213c17ba8fa7dcf2abec6935172

    Here, (empty string) represents an empty string with a length of 0 and \n a line break.

    Signed request

    PUT /exampleobject(%E8%85%BE%E8%AE%AF%E4%BA%91) HTTP/1.1
    Date: Thu, 16 May 2019 06:45:51 GMT
    Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com
    Content-Type: text/plain
    Content-Length: 13
    Content-MD5: mQ/fVh815F3k6TAUm8m0eg==
    x-cos-acl: private
    x-cos-grant-read: uin="100000000011"
    Authorization: q-sign-algorithm=sha1&q-ak=AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q&q-sign-time=1557989151;1557996351&q-key-time=1557989151;1557996351&q-header-list=content-length;content-md5;content-type;date;host;x-cos-acl;x-cos-grant-read&q-url-param-list=&q-signature=3b8851a11a569213c17ba8fa7dcf2abec6935172
    
    ObjectContent

    Downloading object

    Original request

    GET /exampleobject(%E8%85%BE%E8%AE%AF%E4%BA%91)?response-content-type=application%2Foctet-stream&response-cache-control=max-age%3D600 HTTP/1.1
    Date: Thu, 16 May 2019 06:55:53 GMT
    Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com

    Intermediate variables

    • KeyTime = 1557989753;1557996953
    • SignKey = 937914bf490e9e8c189836aad2052e4feeb35eaf
    • UrlParamList = response-cache-control;response-content-type
    • HttpParameters = response-cache-control=max-age%3D600&response-content-type=application%2Foctet-stream
    • HeaderList = date;host
    • HttpHeaders = date=Thu%2C%2016%20May%202019%2006%3A55%3A53%20GMT&host=examplebucket-1250000000.cos.ap-beijing.myqcloud.com
    • HttpString = get\n/exampleobject(tencentcloud)\nresponse-cache-control=max-age%3D600&response-content-type=application%2Foctet-stream\ndate=Thu%2C%2016%20May%202019%2006%3A55%3A53%20GMT&host=examplebucket-1250000000.cos.ap-beijing.myqcloud.com\n
    • StringToSign = sha1\n1557989753;1557996953\n54ecfe22f59d3514fdc764b87a32d8133ea611e6\n
    • Signature = 01681b8c9d798a678e43b685a9f1bba0f6c0e012

    Here, \n represents a line break.

    Signed request

    GET /exampleobject(%E8%85%BE%E8%AE%AF%E4%BA%91)?response-content-type=application%2Foctet-stream&response-cache-control=max-age%3D600 HTTP/1.1
    Date: Thu, 16 May 2019 06:55:53 GMT
    Host: examplebucket-1250000000.cos.ap-beijing.myqcloud.com
    Authorization: q-sign-algorithm=sha1&q-ak=AKIDQjz3ltompVjBni5LitkWHFlFpwkn9U5q&q-sign-time=1557989753;1557996953&q-key-time=1557989753;1557996953&q-header-list=date;host&q-url-param-list=response-cache-control;response-content-type&q-signature=01681b8c9d798a678e43b685a9f1bba0f6c0e012

    Was this page helpful?

    Was this page helpful?

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