Request Signature

Last updated: 2021-04-26 15:38:29

    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.

    1. Sort the KeyList in lexicographical order.
    2. 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.
    3. 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

    Use the HttpMethod, UriPathname, HttpParameters, and HttpHeaders to generate HttpString 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