All Products
Search
Document Center

Object Storage Service:A V4 signature in a PostObject request

Last Updated:Oct 28, 2024

To ensure the validity and security of a PostObject request, you must include a signature in the PostObject request. The V4 signature in the PostObject request is calculated by encrypting a series of request parameters, including policy and expiration, based on the AccessKey secret, the current time, and the region. After the application server generates a signature, the application server returns information including the signature and upload policy to the client. The client uses the information to create an upload request. After OSS receives the upload request, OSS verifies the validity of the signature. Only requests that include a valid signature are allowed. Requests that fail the signature verification are denied.

Signature in a PostObject request

To enhance data security, the PostObject request integrates the V4 signature algorithm. The form elements and policy form field play a key role in ensuring the validity and security of PostObject requests.

Form elements

A form is a collection of fields that are actually carried in a PostObject request to pass information about the object that you want to upload and its metadata. The following table describes the unique form elements of a V4 signature in a PostObject request. For more information about the common form elements, see Form elements.

Element

Type

Required

Description

x-oss-signature-version

String

Yes

The signature version and the algorithm used to calculate the signature. Set the value to OSS4-HMAC-SHA256.

x-oss-credential

String

Yes

The credentials that you can use to calculate the signature. Format:

<AccessKeyId>/<date>/<region>/oss/aliyun_v4_request
  • AccessKeyId: the AccessKey ID of the AccessKey pair.

  • date: the date when the request was initiated. Format: YYYYMMDD. Example: 20231203.

  • region: the ID of the Alibaba Cloud region in which the bucket you want to access is located. Example: cn-hangzhou.

  • oss: the name of the requested service. Set the value to oss.

  • aliyun_v4_request: the description of the signature version in the request. Set the value to aliyun_v4_request.

x-oss-date

String

Yes

The time when the request was initiated. The time must follow the ISO 8601 standard. Example: 20231203T121212Z.

  • An offset of up to 15 minutes after the request was initiated is allowed. Therefore, the time when the server receives the request can be up to 15 minutes later than the time specified by x-oss-date. This ensures that the requests can be processed as expected even if network transmission latency or time difference between the client and the server exists.

  • The request has a validity period of up to seven days. Seven days after the time specified by x-oss-date, OSS denies the request and an error is reported. This ensures the timeliness and security of requests and prevents malicious submission of expired or signed requests.

  • The time specified by x-oss-date is used as the timestamp for the string to sign. The value must be the same as that of the date field in the derived keys and that of the x-oss-date field in the policy form field.

x-oss-signature

String

Yes

The description used for signature verification. The value is calculated by encrypting the Base64-encoded policy string by using HMAC-SHA256, and then converting the binary hash obtained by using HMAC-SHA256 into hexadecimal format.

policy

The policy form field in a PostObject request is used to specify the expiration time and conditions of the PostObject request that you initiate to upload an object by using an HTML form. The value of the policy form field is a JSON string that restricts a PostObject request by specifying multiple parameters, such as the bucket name to which you want to upload the object, the prefix in the object name, the validity period of the request, the allowed HTTP methods, and the object size and content.

Important

The policy form field must contain the expiration and conditions parameters. The following field for the Conditions parameter contains optional parameters, such as the x-oss-security-token parameter, which is only required when you use a security token to construct a signature in the PostObject request. The x-oss-security-token parameter is not required when you use AccessKey pairs to construct signatures in PostObject requests.

{
  "expiration": "2023-12-03T13:00:00.000Z",
  "conditions": [
    {"bucket": "examplebucket"},
    {"x-oss-signature-version": "OSS4-HMAC-SHA256"},
    {"x-oss-credential": "AKIDEXAMPLE/20231203/cn-hangzhou/oss/aliyun_v4_request"},
    {"x-oss-security-token": "CAIS******"},
    {"x-oss-date": "20231203T121212Z"},
    ["content-length-range", 1, 10],
    ["eq", "$success_action_status", "201"],
    ["starts-with", "$key", "user/eric/"],
    ["in", "$content-type", ["image/jpg", "image/png"]],
    ["not-in", "$cache-control", ["no-cache"]]
  ]
}

Required parameters in the policy form field

  • expiration

    The expiration parameter specifies the expiration time of the request. The time must follow the ISO 8601 standard and must be in GMT. For example, 2023-12-03T13:00:00.000Z specifies that the PostObject request must be sent before 13:00 on December 3, 2023.

  • conditions

    The conditions parameter is a list that specifies the valid values of the form fields in the PostObject request.

    Parameter

    Type

    Required

    Description

    Matching mode

    bucket

    String

    No

    The name of the bucket.

    bucket

    x-oss-signature-version

    String

    Yes

    The signature version and the algorithm used to calculate the signature. Set the value to OSS4-HMAC-SHA256.

    x-oss-signature-version

    x-oss-credential

    String

    Yes

    The credentials that you can use to calculate the signature. Format:

    <AccessKeyId>/<date>/<region>/oss/aliyun_v4_request
    • AccessKeyId: the AccessKey ID of the AccessKey pair.

    • date: the date when the request was initiated.

    • region: the ID of the Alibaba Cloud region in which the bucket you want to access is located. Example: cn-hangzhou.

    • oss: the name of the requested service. Set the value to oss.

    • aliyun_v4_request: the description of the signature version in the request. Set the value to aliyun_v4_request.

    x-oss-credential

    x-oss-security-token

    String

    No

    This parameter is required only when you use a security token to construct a signature in the PostObject request. You can call the AssumeRole operation of STS to obtain a security token.

    x-oss-security-token

    x-oss-date

    String

    Yes

    The time when the request was initiated. The time must follow the ISO 8601 standard. Example: 20231203T121212Z.

    • An offset of up to 15 minutes after the request was initiated is allowed. Therefore, the time when the server receives the request can be up to 15 minutes later than the time specified by x-oss-date. This ensures that the requests can be processed as expected even if network transmission latency or time difference between the client and the server exists.

    • The request has a validity period of up to seven days. Seven days after the time specified by x-oss-date, OSS denies the request and an error is reported. This ensures the timeliness and security of requests and prevents malicious submission of expired or signed requests.

    • The time specified by x-oss-date is used as the timestamp for the string to sign. The value must be the same as that of the date field in the derived keys and that of the x-oss-date field in the policy form field.

    x-oss-date

    content-length-range

    String

    No

    The allowed minimum and maximum sizes of the object that you want to upload. Unit: bytes.

    content-length-range

    success_action_status

    String

    No

    The HTTP status code that is returned after the object is uploaded.

    eq, starts-with, in, and not-in

    key

    String

    No

    The name of the object that you want to upload.

    eq, starts-with, in, and not-in

    content-type

    String

    No

    The type of the object that you want to upload.

    eq, starts-with, in, and not-in

    cache-control

    String

    No

    The caching behavior of the object.

    eq, starts-with, in, and not-in

Condition matching modes

Matching mode

Description

content-length-range

The size of the object that you want to upload must be within the range of the supported object size. For example, if the supported object size is 1 to 10 bytes, the condition must be ["content-length-range", 1, 10].

eq

The value of a form field must be exactly the same as the value that is specified in the conditions. For example, if the value of the key form field must be a, you can specify ["eq", "$key", "a"] as the condition.

starts-with

The value of a form field must start with a specific prefix. For example, if the value of the key form field starts with user/user1, you can specify ["starts-with", "$key", "user/user1"] as the condition.

in

The elements that you want to include in the verification. The elements must be specified in the condition string. For example, if you want to verify whether the type of the object that you want to upload is image and want to allow images of multiple formats to be uploaded in a PostObject request, the condition must be ["in", "$content-type", ["image/jpg", "image/png"]].

not-in

The elements that you want to exclude from the verification. The elements must be specified in the condition string. For example, if you want to specify the object caching behavior and exclude the no-cache element, the condition must be ["not-in", "$cache-control", ["no-cache"]].

Escape characters for the policy form field

In the policy form field of a PostObject request, the dollar sign ($) specifies a variable. To describe the dollar sign ($), you must use the following escape character: \$. The following table describes the escape characters used in the JSON string of the policy form field in a PostObject request.

Escape character

Description

\/

Forward slash

\\

Backslash

\"

Double quotation mark

\$

Dollar sign

\b

Space

\f

Form feed

\n

Line break

\r

Carriage return

\t

Horizontal tab

\uxxxx

Unicode characters

Signature calculation process

  1. Create a UTF-8 encoded policy.

  2. Create a string to sign.

    Base64-encode the policy to generate a string that can be transmitted securely as the string to sign.

  3. Calculate the signing key.

    Encrypt the string to sign by using HMAC-SHA256. Use the derived keys of the account as the keys for using HMAC-SHA256.

  4. Calculate the signature.

    Convert the binary hash calculated by using HMAC-SHA256 to a hexadecimal string. The obtained hexadecimal string is the signature used to verify the integrity and validity of the request.

image

Examples

The following sample code provides an example on how to use the preceding policy to calculate a V4 signature for a PostObject request by using OSS SDK for Java:

import com.aliyun.oss.common.utils.BinaryUtil;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
        String accesskeyid =  System.getenv().get("OSS_ACCESS_KEY_ID");
        String accesskeysecret =  System.getenv().get("OSS_ACCESS_KEY_SECRET");

        // Step 1: Create a policy. 
        String policy = "{\n" +
                "  \"expiration\": \"2023-12-03T13:00:00.000Z\",\n" +
                "  \"conditions\": [\n" +
                "    {\"bucket\": \"examplebucket\"},\n" +
                "    {\"x-oss-signature-version\": \"OSS4-HMAC-SHA256\"},\n" +
                "    {\"x-oss-credential\": \""+accesskeyid+"/20231203/cn-hangzhou/oss/aliyun_v4_request\"},\n" +
                "    {\"x-oss-date\": \"20231203T121212Z\"},\n" +
                "    [\"content-length-range\", 1, 10],\n" +
                "    [\"eq\", \"$success_action_status\", \"201\"],\n" +
                "    [\"starts-with\", \"$key\", \"user/eric/\"],\n" +
                "    [\"in\", \"$content-type\", [\"image/jpg\", \"image/png\"]],\n" +
                "    [\"not-in\", \"$cache-control\", [\"no-cache\"]]\n" +
                "  ]\n" +
                "}";

        // Step 2: Create a string to sign. 
        String stringToSign = new String(Base64.encodeBase64(policy.getBytes()));

        // Step 3: Calculate the derived keys. 
        byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), "20231203");
        byte[] dateRegionKey = hmacsha256(dateKey, "cn-hangzhou");
        byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss");
        byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");

        // Step 4: Calculate the signature. 
        byte[] result = hmacsha256(signingKey, stringToSign);
        String signature = BinaryUtil.toHex(result);
        System.out.println("signature:" + signature);

    }

    public static byte[] hmacsha256(byte[] key, String data) {
        try {
            // Initialize the HMAC key specification, set the algorithm to HMAC-SHA256, and use the provided key. 
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");

            // Obtain a Mac instance and use the getInstance method to set the algorithm to HMAC-SHA256. 
            Mac mac = Mac.getInstance("HmacSHA256");
            // Use the key to initialize the Mac instance. 
            mac.init(secretKeySpec);

            // Calculate the HMAC value. Use the doFinal method to receive the data to be calculated and return the calculation results in arrays. 
            byte[] hmacBytes = mac.doFinal(data.getBytes());

            return hmacBytes;
        } catch (Exception e) {
            throw new RuntimeException("Failed to calculate HMAC-SHA256", e);
        }
    }
}

Sample output:

signature:1fd071f7ac52de95b2b131cd070974876c3c4fce20cce3802531bdbee13df8b1