VMRack
Home
Products
Solutions
Pricing
Support
Referral Program
Developer Center
OpenAPI Signature Rules
Region and Endpoint
QueueService
Delete Queue
Create Queue
Update Queue
Queue List
MtsTaskService
Create Task
Retry Task
Get Task Details
Delete Task
List Tasks
Batch Delete Tasks
Get Node Process Types
Batch Retry Tasks
PresetService
Create Preset
Preset Details
Delete Preset
Update Preset
Preset List
WorkflowService
Create Workflow
Copy Workflow
Get Workflow
Delete Workflow
Update Workflow
Workflow List
Domain Management
Query the list of domain names
Object Management
Object - Obtain object information
Object - Delete object
Object - Interrupt shard upload, copy, move, modify storage type task
Object - Complete shard copy, move, modify storage type task
Object - Copy object
Object - Create a shard copy, move, modify storage type task
Object - Create directory
Object - Delete directory
Object - Get object list
Object - Get metadata
Object - Update metadata
Object - Move object
Object - Execute shard copy, move, modify storage type
Object - Complete multipart upload task
Object - Create multipart upload task
Object - Pre-download
Object - Pre-sign
Object - Modify object storage type
Bucket Management
Bucket - Delete all bucket data
Bucket - Query bucket information
Bucket - Create bucket
Bucket - Delete bucket
Bucket - Modify bucket access control permissions
Bucket - Get CORS configuration
Bucket - Update CORS configuration
Bucket - Create CORS configuration
Bucket - Delete CORS configuration
Bucket - Get CORS configuration list
Bucket - Query bucket lifecycle list
Bucket - Update bucket lifecycle
Bucket - Create bucket lifecycle
Bucket - Delete bucket lifecycle
Bucket - Query bucket list
Bucket - Add client cache Maxage
Bucket - Get referer configuration
Bucket - Edit referer configuration
Version Notes
  1. Developer Center
  2. /
  3. OpenAPI Signature Rules

OpenAPI Signature Rules

VM Mode API Signature Authentication Developer Documentation (VM4-HMAC-SHA256)

This API utilizes the VM4-HMAC-SHA256 signature algorithm to ensure the authenticity of the request source, data integrity, and protection against replay attacks. All requests must include signature information within the headers.

1. Signature Parameters Overview

parameter

value

illustrate

Header Prefix

x-vm-

All custom headers begin with this.

Service Name

v3

Service Identity within the Signing Scope

Algorithm Identifier Prefix

VM4

The starting identifier for the Authorization header.

Scope Suffix

vm4_request

The ending character of the derived key calculation

2. Required Header Fields

Header Key

Example Value

illustrate

x-vm-date

20260326T113306Z

The UTC time at which the request was issued, in the format: YYYYMMDDTHHMMSSZ

x-vm-content-sha256

e3b0c442...

The SHA256 hash of the request body (lowercase hexadecimal).

Authorization

VM4-HMAC-SHA256 ...

Complete Signature Credential String

Notice:The server validates x-vm-date; if the deviation from the server's time exceeds 15 minutes, the request will be rejected.

3. Signature Calculation Steps

Step 1:Constructing a Canonical Request

Concatenate the following strings in order (separated by \n):

  • HTTPMethod: eg. GET, POST。

  • CanonicalURI: The encoded path (e.g., /api/v1/instances). If empty, / is used.

  • CanonicalQueryString: A string consisting of the parameters sorted in ascending ASCII order and URL-encoded. If there are no parameters, the string is empty.

  • CanonicalHeaders: Must include host, x-vm-content-sha256, and x-vm-date. The format is: key:value\n (Note: keys must be lowercase).。

  • Blank Line: After the headers have been concatenated, an additional newline character must be appended.

  • SignedHeaders: A list of header keys included in the signature, lowercase and separated by semicolons.。

  • PayloadHash: The value of x-vm-content-sha256 (i.e., the SHA256 hexadecimal string of the Body).。

Example

GET
/v1/instances
Limit=10&status=running
host:api.example.com
x-vm-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-vm-date:20260326T113306Z

host;x-vm-content-sha256;x-vm-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Step 2:Constructing the String to Sign

Concatenate the metadata and the canonical request hash generated in Step 1, in the following order (separated by \n).:

  • Algorithm: Fixed Value VM4-HMAC-SHA256.

  • RequestDateTime: The value of x-vm-date (e.g., 20260326T113306Z).

  • CredentialScope: A string containing the date, region, and service identifier. The format is: {DateStamp}/{Region}/v3/vm4_request.

  • DateStamp: The format is YYYYMMDD (e.g., 20260326).

  • Region: The ID or name of the target region for the request (optional)—e.g., 1965717130594750464 or cn-north-1.

  • HashedCanonicalRequest: Compute the SHA256 hash of the entire Canonical Request string constructed in Step 1, and convert it into a lowercase hexadecimal string.

Example

VM4-HMAC-SHA256
20260326T113306Z
20260326/cn-north-1/v3/vm4_request
765e92d7b1d12c8a3e8a4d2f9b8c7a6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a

Step 3:Generate Derived Key (Signing Key)

The derived key is obtained by performing multiple hash iterations on the SecretKey. Please execute the HMAC-SHA256 operations in the following order (pseudocode logic).:

  kDate: Hash the DateStamp (YYYYMMDD) using "VM4" + SecretKey as the key. HMAC-SHA256("VM4" + SecretKey, "20260326")
kRegion: Use the kDate obtained in the previous step as the key to hash the Region (e.g., cn-north-1). HMAC-SHA256(kDate, "cn-north-1")

  kService: Use the kRegion obtained in the previous step as the key to hash the ServiceName (fixed as "v3"). HMAC-SHA256(kRegion, "v3")

kSigning: Using the kService obtained in the previous step as the key, hash the Suffix (fixed as "vm4_request"). HMAC-SHA256(kService, "vm4_request")

Perform HMAC-SHA256 calculations sequentially using your SecretKey.:

// Note: VM4 is used as a prefix for the SecretKey.
kDate    := hmacSha256([]byte("VM4" + secretKey), "20260326")
kRegion  := hmacSha256(kDate, "cn-north-1")
kService := hmacSha256(kRegion, "v3")
kSigning := hmacSha256(kService, "vm4_request") // The resulting kSigning is used in Step 4.

Step 4:Calculate the Final Signature

Use the generated derived key (Signing Key) to perform the final integrity signature on the offset and request metadata.

  Key: Use the final binary byte array, kSigning, calculated in Step 3.

  Data: Use the complete "String to Sign" string constructed in Step 2.

HMAC Calculation:  Use the HMAC-SHA256 algorithm to hash the "String To Sign," using kSigning as the key.

Hexadecimal Conversion:  Convert the binary result obtained in the previous step into a lowercase hexadecimal string. This constitutes the final Signature.

// Use the result kSigning from Step 3 and the result stringToSign from Step 2.
signatureBytes := hmacSha256(kSigning, stringToSign)
signature := hex.EncodeToString(signatureBytes) 

4. Authorization Header Example

 Authorization: VM4-HMAC-SHA256 Credential=AK_EXAMPLE/20260326/region-1/v3/vm4_request, SignedHeaders=host;x-vm-content-sha256;x-vm-date, Signature=fe5f...

5. Developer Code Reference (Go)

The following example demonstrates how to manually calculate and add a VM mode signature to an HTTP request without relying on external frameworks.

package main
 
import (
    "bytes"
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "net/http"
    "time"
)
 
// HmacSha256 tool
func hmacSha256(key []byte, data string) []byte {
    h := hmac.New(sha256.New, key)
    h.Write([]byte(data))
    return h.Sum(nil)
}
 
// (Signing Key)
func getVM4SigningKey(secretKey, dateStamp, regionName string) []byte {
    kDate := hmacSha256([]byte("VM4"+secretKey), dateStamp)
    kRegion := hmacSha256(kDate, regionName)
    kService := hmacSha256(kRegion, "v3") // ServiceName is v3
    kSigning := hmacSha256(kService, "vm4_request")
    return kSigning
}
 
func signVMRequest(req *http.Request, ak, sk, region, payloadHash string) {
    now := time.Now().UTC()
    amzDate := now.Format("20060102T150405Z")
    dateStamp := now.Format("20060102")
 
    // 1. set Header
    req.Header.Set("x-vm-date", amzDate)
 
    // Calculate Payload Hash (Assuming no Body, or Body has already been processed)
    if payloadHash == "" {
        payloadHash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
    }
    req.Header.Set("x-vm-content-sha256", payloadHash)
 
    // 2. Canonical Request
    signedHeaders := "host;x-vm-content-sha256;x-vm-date"
    canonicalRequest := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s",
        req.Method,
        req.URL.Path,
        req.URL.RawQuery,
        "host:"+req.Host,
        "x-vm-content-sha256:"+payloadHash,
        "x-vm-date:"+amzDate+"\n",
        signedHeaders,
        payloadHash,
    )
 
    // 3. StringToSign
    credentialScope := fmt.Sprintf("%s/%s/v3/vm4_request", dateStamp, region)
    hash := sha256.Sum256([]byte(canonicalRequest))
    stringToSign := fmt.Sprintf("VM4-HMAC-SHA256\n%s\n%s\n%s",
        amzDate,
        credentialScope,
        hex.EncodeToString(hash[:]),
    )
    fmt.Println("StringToSign:", stringToSign)
 
    // 4. sign
    signingKey := getVM4SigningKey(sk, dateStamp, region)
    signature := hex.EncodeToString(hmacSha256(signingKey, stringToSign))
 
    // 5. set Authorization Header
    authHeader := fmt.Sprintf("VM4-HMAC-SHA256 Credential=%s/%s, SignedHeaders=%s, Signature=%s",
        ak, credentialScope, signedHeaders, signature)
    req.Header.Set("Authorization", authHeader)
}
 
func main() {
    var body = []byte(`{"offset":1,"limit":1}`)
    // Payload Hash
    hash := sha256.Sum256(body)
    payloadHash := hex.EncodeToString(hash[:])
    req, _ := http.NewRequest("GET", "http://127.0.0.1:8080/aaa-2100002392/?delimiter=%2F&encoding-type=url&fetch-owner=true&list-type=2&prefix=", bytes.NewReader(body))
    req.Host = "127.0.0.1:8080"
 
    ak := "CUS1****SVTK"
    sk := "OPD3****E27G"
    region := "1965717130594750464"
 
    signVMRequest(req, ak, sk, region, payloadHash)
 
    fmt.Println("Authorization Header:", req.Header.Get("Authorization"))
}

6. Signature Debugging Steps

To ensure successful integration, please check in the following order.:

  •   Path Encoding:The CanonicalURI must start with a '/'. If the path is empty, use '/'.

  •   Parameter Sorting:The parameters in the CanonicalQueryString must be arranged in ascending ASCII order of their key names.

  • Lowercase Conversion:All key names in SignedHeaders must be converted to lowercase.

  • Hash Consistency:x-vm-content-sha256 must exactly match the SHA256 value of the actual content in the request body.

7. Common Error Codes

Error Code

illustrate

UNAUTHORIZED: Signature mismatch

The signature calculation is inconsistent. Please check your keys and the logic for constructing the Canonical Request.

UNAUTHORIZED: x-amz-date skew too large

The client time deviation exceeds 15 minutes. Please synchronize the NTP time.

UNAUTHORIZED: Missing x-vm-date

x-vm-date is missing or has an incorrect format.

VMRack
  • Products
  • VPS Hosting
  • VPS Hosting
    Unmetered
  • Bare Metal
  • GPU Rental
  • CDN
    Public Beta
  • Custom CDN
  • Object Storage
    Public Beta
  • Transcoder
    Public Beta
  • Solutions
  • Bring Your Own IP (BYOIP)
  • Customized Server Solutions
  • Colocation Services
  • Resources
  • Pricing
  • Help Documentation
  • Articles
  • Developer Center
  • Referral Program
  • Contact
  • Company
  • About Us
  • Terms of Service
  • User Agreement
  • Privacy Policy
  • Service Level Agreement