All Products
Search
Document Center

Machine Translation:Signature mechanism

Last Updated:Sep 15, 2023

Signature Mechanism

The ROA-style API signature consists of two parts: the public request header (the HTTP protocol header parameter and the Alibaba Cloud Protocol Header parameter) and the CanonicalizedResource (the canonical resource).It is recommended to use SDK access whenever possible. Users do not have to pay attention to the signature details.

Name

Description

Authorization

The authentication information used to verify the validity of the request is in the form of ACS AccessKeyId: signature.

Content-Length

The length of the HTTP request content defined in RFC 2616.

Content-Type

The HTTP request content type defined in RFC 2616.

Content-MD5

The 128-bit MD5 hash value of the HTTP protocol message body is converted to BASE64 encoding. To prevent all requests from being tampered with, it is recommended that all requests be appended with this information.

Date

Describes the request time in GMT format, such as: Wed, 26 Aug. 2015 17:01:00 GMT.

Accept

Required client return value type, only supports application/json.

Host

Access Host value, for example: mt.cn-hangzhou.aliyuncs.com.

x-acs-signature-nonce

A unique random number used to prevent network replay attacks. Users use different random values ​​in different requests.

x-acs-signature-method

Signature method, currently supports only HMAC-SHA1.

x-acs-version

API version, if not filled in, the server will adopt the highest version by default.

Signature calculation method

ROA-style API requests use the standard Authorization header to sign their own requests. The request format is as follows:

Authorization: acs AccessKeyId:Signature

  1. Calculate the MD5 value of the body, run its encoding in base64, then set the encoded value to the header.

  2. Construct a normalized Header string using the Header parameter in the request.

    headerStringToSign = 
    HTTP-Verb + "\n" +         //HTTP_Verb Only POST is supported
    Accept + "\n" +            //Accept is application/json
    Content-MD5 + "\n" +       //MD5 value calculated in step 1
    Content-Type + "\n" +      //Content-Type is application/json;chrset=utf-8
    Date + "\n" +              //Date is GMT
    “x-acs-signature-method:HMAC-SHA1\n” + 
    “x-acs-signature-nonce:” + ${x-acs-signature-nonce} + "\n" +
    “x-acs-version:2019-01-02" + "\n";
  3. CanonicalizedResource indicates the specification description of the client that wants to access the resource. The sub-resource and query are arranged in lexicographical order, from small to large, and the sub-resource string (all parameters after ?) is generated as a delimiter. The example is as follows (All alimt requests are without parameters).

    resourceStringToSign = URI;
  4. Construct the normalized string constructed in the previous two steps into the string to be signed according to the following rules.

    stringToSign = headerStringToSign + resourceStringToSign;

    1. Calculate the HMAC value of the string to be signed (StringToSign) according to the definition of RFC2104, encode the above HMAC value into a string according to the Base64 encoding rule, and add the AccessKeyId at the front to get the signature value (Authorization). The example is as follows:

      Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
      Authorization = "acs " + AccessKeyId + ":" + Signature

Example Coding (java)

package com.alibaba.intl.translate.service.impl.displaytitle;

import java.util.Map;

import jodd.util.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;

public class Sender {

        /*
         * Calculate MD5+BASE64
         */
        public static String MD5Base64(String s) {
            if (s == null)
                return null;
            String encodeStr = "";
            byte[] utfBytes = s.getBytes();
            MessageDigest mdTemp;
            try {
                mdTemp = MessageDigest.getInstance("MD5");
                mdTemp.update(utfBytes);
                byte[] md5Bytes = mdTemp.digest();

                encodeStr = Base64.encodeToString(md5Bytes);
            } catch (Exception e) {
                throw new Error("Failed to generate MD5 : " + e.getMessage());
            }
            return encodeStr;
        }
        /*
         * Calculate HMAC-SHA1
         */
        public static String HMACSha1(String data, String key) {
            String result;
            try {
                SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
                Mac mac = Mac.getInstance("HmacSHA1");
                mac.init(signingKey);
                byte[] rawHmac = mac.doFinal(data.getBytes());
                result = Base64.encodeToString(rawHmac);
            } catch (Exception e) {
                throw new Error("Failed to generate HMAC : " + e.getMessage());
            }
            return result;
        }
        /*
         * To get the time
         */
        public static String toGMTString(Date date) {
            SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
            df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
            return df.format(date);
        }
        /*
         * Send POST request
         */
        public static String sendPost(String url, String body, String ak_id, String ak_secret) {
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                URL realUrl = new URL(url);
                /*
                 * http header parameter
                 */
                String method = "POST";
                String accept = "application/json";
                String content_type = "application/json;chrset=utf-8";
                String path = realUrl.getFile();
                String date = toGMTString(new Date());
                String host = realUrl.getHost();
                String bodyMd5 = MD5Base64(body);
                String uuid = UUID.randomUUID().toString();
                String stringToSign = method + "\n" + accept + "\n" + bodyMd5 + "\n" + content_type + "\n" + date + "\n"
                        + "x-acs-signature-method:HMAC-SHA1\n"
                        + "x-acs-signature-nonce:" + uuid + "\n"
                        + "x-acs-version:2019-01-02\n"
                        + path;
                String signature = HMACSha1(stringToSign, ak_secret);
                String authHeader = "acs " + ak_id + ":" + signature;
                URLConnection conn = realUrl.openConnection();
                conn.setRequestProperty("Accept", accept);
                conn.setRequestProperty("Content-Type", content_type);
                conn.setRequestProperty("Content-MD5", bodyMd5);
                conn.setRequestProperty("Date", date);
                conn.setRequestProperty("Host", host);
                conn.setRequestProperty("Authorization", authHeader);
                conn.setRequestProperty("x-acs-signature-nonce", uuid);
                conn.setRequestProperty("x-acs-signature-method", "HMAC-SHA1");
                conn.setRequestProperty("x-acs-version", "2019-01-02");  
                conn.setDoOutput(true);
                conn.setDoInput(true);
                out = new PrintWriter(conn.getOutputStream());
                out.print(body);
                out.flush();
                InputStream is;
                HttpURLConnection httpconn = (HttpURLConnection) conn;
                if (httpconn.getResponseCode() == 200) {
                    is = httpconn.getInputStream();
                } else {
                    is = httpconn.getErrorStream();
                }
                in = new BufferedReader(new InputStreamReader(is));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("Exception in parameter sending POST request!" + e);
                e.printStackTrace();
            }
            finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            return result;
        }

}