All Products
Search
Document Center

Object Storage Service:Include a V4 signature in the Authorization header (recommended)

Last Updated:Mar 20, 2026

Include a V4 signature in the Authorization request header to authenticate requests to OSS. The OSS SDK handles this automatically—implement the V4 signature algorithm yourself only if you cannot use the SDK.

SDK signature implementation

Before building the V4 signature algorithm yourself, review how the OSS SDK implements it. The following table lists the V4 signer source files for each SDK.

SDKV4 signature implementation
JavaOSSV4Signer.java
Pythonv4.py
Gov4.go
JavaScriptclient.js
PHPSignerV4.php
C#SignerV4.cs
AndroidOSSV4Signer.java
SwiftSignerV4.swift
Objective-COSSV4Signer.m
C++SignerV4.cc
Coss_auth.c

Authorization request header

Include an Authorization header in every OSS request. OSS calculates the expected signature and compares it with the value in this header—matching signatures mean the request is authenticated.

The header format is:

Authorization: OSS4-HMAC-SHA256 Credential=<AccessKeyId>/<SignDate>/<SignRegion>/oss/aliyun_v4_request, AdditionalHeaders=<AdditionalHeadersVal>, Signature=<SignatureVal>
ComponentDescription
OSS4-HMAC-SHA256The signature algorithm: OSS V4 (OSS4) using HMAC-SHA256.
CredentialYour AccessKey ID and signing scope. Format: <AccessKeyId>/<SignDate>/<SignRegion>/oss/aliyun_v4_request.
AdditionalHeadersLowercase header names of optional headers included in signing, sorted lexicographically and separated by semicolons. Example: content-disposition;content-length.
SignatureThe calculated signature: 64 lowercase hexadecimal digits representing a 256-bit value. Example: 3938**********************************dcdc.

Credential sub-fields:

Sub-fieldDescription
AccessKeyIdYour AccessKey ID.
SignDateThe signature date in YYYYMMDD format.
SignRegionThe region ID of the endpoint, such as cn-hangzhou.
ossFixed string identifying Object Storage Service (OSS).
aliyun_v4_requestFixed string identifying the V4 signature version.

Signature calculation

The V4 signature requires three steps: build a canonical request, derive a string-to-sign from it, then compute the signature using a derived signing key.

Helper functions

Implement the following functions before starting. They are used throughout the signing process.

FunctionDescription
Lowercase()Convert a string to lowercase.
Trim()Remove leading and trailing whitespace from a string.
URI-encode()Percent-encode each byte using uppercase hex. Do not encode unreserved characters (A–Z, a–z, 0–9, -, _, ., ~). Do not encode forward slashes (/) in the URI path.
SHA256Hash()Return the SHA-256 hash of the input.
HMAC-SHA256(key, data)Compute HMAC using SHA-256. The key is a byte array, not a hex string.
HEX()Encode a byte array as lowercase hexadecimal.

Signing flow

CanonicalRequest  =  HTTPVerb + "\n" + CanonicalURI + "\n" + CanonicalQueryString + "\n"
                   + CanonicalHeaders + "\n" + AdditionalHeaders + "\n" + HashedPayload

StringToSign  =  "OSS4-HMAC-SHA256" + "\n" + TimeStamp + "\n" + Scope + "\n"
               + HEX(SHA256Hash(CanonicalRequest))

DateKey              =  HMAC-SHA256("aliyun_v4" + SK, Date)
DateRegionKey        =  HMAC-SHA256(DateKey, Region)
DateRegionServiceKey =  HMAC-SHA256(DateRegionKey, "oss")
SigningKey           =  HMAC-SHA256(DateRegionServiceKey, "aliyun_v4_request")

Signature  =  HEX(HMAC-SHA256(SigningKey, StringToSign))

Step 1: Construct a canonical request

A canonical request is a standardized string that captures the essential parts of the HTTP request.

HTTPVerb + "\n" +
CanonicalURI + "\n" +
CanonicalQueryString + "\n" +
CanonicalHeaders + "\n" +
AdditionalHeaders + "\n" +
HashedPayload

HTTPVerb

The HTTP method: PUT, GET, POST, HEAD, DELETE, or OPTIONS.

CanonicalURI

The URI-encoded resource path, excluding the query string. Do not encode forward slashes (/).

TargetResource pathCanonicalURI
OSS service/URI-encode("/")
Bucket/examplebucket/URI-encode("/examplebucket/")
Object/examplebucket/exampleobjectURI-encode("/examplebucket/exampleobject")

CanonicalQueryString

URI-encoded query parameters sorted lexicographically by encoded name. Sorting happens after encoding.

  • Connect each name and value with =. Separate parameters with &.

  • If no query parameters exist, use an empty string ("").

Examples:

InputCanonicalQueryString
prefix=somePrefix&marker=someMarker&max-keys=20URI-encode("marker")+"="+URI-encode("someMarker")+"&"+URI-encode("max-keys")+"="+URI-encode("20")+"&"+URI-encode("prefix")+"="+URI-encode("somePrefix")
?acl (name only, no value)URI-encode("acl")
(no query parameters)""

CanonicalHeaders

A newline-terminated list of request headers that participate in signing. Each line has the format:

Lowercase(<HeaderName>) + ":" + Trim(<value>) + "\n"

Headers fall into three categories:

CategoryHeaders
Always requiredx-oss-content-sha256 (only UNSIGNED-PAYLOAD is currently supported)
Included when presentContent-Type, Content-MD5, and all x-oss-* headers (e.g., x-oss-date, x-oss-security-token)
Optional (sign if listed in AdditionalHeaders)Any additional headers you choose to include

The x-oss-date value must use ISO 8601 format, such as 20231203T121212Z. When accessing OSS with a Security Token Service (STS) temporary credential, pass the security token as x-oss-security-token:<token>.

Example:

content-disposition:attachment
content-length:3
content-md5:ICy5YqxZB1uWSwcVLSNLcA==
content-type:text/plain
x-oss-content-sha256:UNSIGNED-PAYLOAD
x-oss-date:20250328T101048Z

AdditionalHeaders

Lowercase header names of any optional headers included in signing, sorted lexicographically and separated by semicolons. This must match the AdditionalHeaders field in the Authorization header. Do not list required headers here.

Example: content-disposition;content-length

HashedPayload

The SHA-256 hash of the request body. Only UNSIGNED-PAYLOAD is currently supported.

Step 2: Construct a string-to-sign

"OSS4-HMAC-SHA256" + "\n" +
TimeStamp + "\n" +
Scope + "\n" +
HEX(SHA256Hash(CanonicalRequest))
ParameterDescription
OSS4-HMAC-SHA256Fixed value. The signature algorithm identifier.
TimeStampThe current UTC time in ISO 8601 format, such as 20250320T083322Z.
Scope<SignDate>/<SignRegion>/oss/aliyun_v4_request. Binds the signature to a specific date, region, and service.
HEX(SHA256Hash(CanonicalRequest))The SHA-256 hash of the canonical request, encoded as lowercase hex.

Scope sub-fields:

Sub-fieldDescription
SignDateThe signing date in YYYYMMDD format.
SignRegionThe region ID, such as cn-hangzhou.
ossFixed string for the service name.
aliyun_v4_requestFixed string for the signature version.

Step 3: Calculate the signature

Step 3a — Derive the signing key:

DateKey              = HMAC-SHA256("aliyun_v4" + SK, Date)
DateRegionKey        = HMAC-SHA256(DateKey, Region)
DateRegionServiceKey = HMAC-SHA256(DateRegionKey, "oss")
SigningKey           = HMAC-SHA256(DateRegionServiceKey, "aliyun_v4_request")
VariableDescription
SKYour AccessKey Secret.
DateThe signing date in YYYYMMDD format. Must match SignDate in the scope.
RegionThe region ID, such as cn-hangzhou. Must match SignRegion in the scope.

Step 3b — Calculate the signature:

Signature = HEX(HMAC-SHA256(SigningKey, StringToSign))

Signature calculation example

This example demonstrates the full signing process for a PutObject request.

Input parameters

ParameterValue
AccessKeyIdLTAI****************
AccessKeySecretyourAccessKeySecret
Timestamp20250411T064124Z
Bucketexamplebucket
Objectexampleobject
Regioncn-hangzhou

Step 1: Canonical request

PUT
/examplebucket/exampleobject

content-disposition:attachment
content-length:3
content-md5:ICy5YqxZB1uWSwcVLSNLcA==
content-type:text/plain
x-oss-content-sha256:UNSIGNED-PAYLOAD
x-oss-date:20250411T064124Z

content-disposition;content-length
UNSIGNED-PAYLOAD

Step 2: String-to-sign

OSS4-HMAC-SHA256
20250411T064124Z
20250411/cn-hangzhou/oss/aliyun_v4_request
c46d96390bdbc2d739ac9363293ae9d710b14e48081fcb22cd8ad54b63136eca

Step 3: Signature

SigningKey (shown in hexadecimal for readability — different parameter combinations produce different values):

3543b7686e65eda71e5e5ca19d548d78423c37e8ddba4dc9d83f90228b457c76

Signature:

053edbf550ebd239b32a9cdfd93b0b2b3f2d223083aa61f75e9ac16856d61f23