All Products
Search
Document Center

Signature mechanism

Last Updated: Jul 05, 2019

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.

    1. headerStringToSign =
    2. HTTP-Verb + "\n" + //HTTP_Verb Only POST is supported
    3. Accept + \n + //Accept is application/json
    4. Content-MD5 + "\n" + //MD5 value calculated in step 1
    5. Content-Type + "\n" + //Content-Type is application/json;chrset=utf-8
    6. Date + "\n" + //Date is GMT
    7. x-acs-signature-method:HMAC-SHA1\n +
    8. x-acs-signature-nonce:” + ${x-acs-signature-nonce} + "\n" +
    9. 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 qurey 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).

    1. 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:
      1. Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
      2. Authorization = "acs " + AccessKeyId + ":" + Signature

Example Coding (java)

  1. import sun.misc.BASE64Encoder;
  2. import javax.crypto.Mac;
  3. import javax.crypto.spec.SecretKeySpec;
  4. import java.io.*;
  5. import java.net.HttpURLConnection;
  6. import java.net.URL;
  7. import java.net.URLConnection;
  8. import java.security.MessageDigest;
  9. import java.text.SimpleDateFormat;
  10. import java.util.Date;
  11. import java.util.Locale;
  12. import java.util.UUID;
  13. public class Sender {
  14. /*
  15. * MD5+BASE64
  16. */
  17. public static String MD5Base64(String s) {
  18. if (s == null)
  19. return null;
  20. String encodeStr = "";
  21. byte[] utfBytes = s.getBytes();
  22. MessageDigest mdTemp;
  23. try {
  24. mdTemp = MessageDigest.getInstance("MD5");
  25. mdTemp.update(utfBytes);
  26. byte[] md5Bytes = mdTemp.digest();
  27. BASE64Encoder b64Encoder = new BASE64Encoder();
  28. encodeStr = b64Encoder.encode(md5Bytes);
  29. } catch (Exception e) {
  30. throw new Error("Failed to generate MD5 : " + e.getMessage());
  31. }
  32. return encodeStr;
  33. }
  34. /*
  35. * HMAC-SHA1
  36. */
  37. public static String HMACSha1(String data, String key) {
  38. String result;
  39. try {
  40. SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
  41. Mac mac = Mac.getInstance("HmacSHA1");
  42. mac.init(signingKey);
  43. byte[] rawHmac = mac.doFinal(data.getBytes());
  44. result = (new BASE64Encoder()).encode(rawHmac);
  45. } catch (Exception e) {
  46. throw new Error("Failed to generate HMAC : " + e.getMessage());
  47. }
  48. return result;
  49. }
  50. /*
  51. * Get Time
  52. */
  53. public static String toGMTString(Date date) {
  54. SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
  55. df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
  56. return df.format(date);
  57. }
  58. /*
  59. * Send a POST request
  60. */
  61. public static String sendPost(String url, String body, String ak_id, String ak_secret) {
  62. PrintWriter out = null;
  63. BufferedReader in = null;
  64. String result = "";
  65. try {
  66. URL realUrl = new URL(url);
  67. /*
  68. * http header parameter
  69. */
  70. String method = "POST";
  71. String accept = "application/json";
  72. String content_type = "application/json;chrset=utf-8";
  73. String path = realUrl.getFile();
  74. String date = toGMTString(new Date());
  75. String host = realUrl.getHost();
  76. // 1.Do MD5+BASE64 encryption for the body
  77. String bodyMd5 = MD5Base64(body);
  78. String uuid = UUID.randomUUID().toString();
  79. String stringToSign = method + "\n" + accept + "\n" + bodyMd5 + "\n" + content_type + "\n" + date + "\n"
  80. + "x-acs-signature-method:HMAC-SHA1\n"
  81. + "x-acs-signature-nonce:" + uuid + "\n"
  82. + "x-acs-version:2019-01-02\n"
  83. + path;
  84. // 2.Calculation HMAC-SHA1
  85. String signature = HMACSha1(stringToSign, ak_secret);
  86. // 3.Get authorization header
  87. String authHeader = "acs " + ak_id + ":" + signature;
  88. // open url connection
  89. URLConnection conn = realUrl.openConnection();
  90. // Set general request properties
  91. conn.setRequestProperty("Accept", accept);
  92. conn.setRequestProperty("Content-Type", content_type);
  93. conn.setRequestProperty("Content-MD5", bodyMd5);
  94. conn.setRequestProperty("Date", date);
  95. conn.setRequestProperty("Host", host);
  96. conn.setRequestProperty("Authorization", authHeader);
  97. conn.setRequestProperty("x-acs-signature-nonce", uuid);
  98. conn.setRequestProperty("x-acs-signature-method", "HMAC-SHA1");
  99. conn.setRequestProperty("x-acs-version", "2019-01-02"); // 版本可选
  100. // To send a POST request, you must set the following two lines.
  101. conn.setDoOutput(true);
  102. conn.setDoInput(true);
  103. // Get the output stream corresponding to the URLConnection object
  104. out = new PrintWriter(conn.getOutputStream());
  105. // Send request parameter
  106. out.print(body);
  107. // Flush output stream buffer
  108. out.flush();
  109. // Define the BufferedReader input stream to read the response of the URL
  110. InputStream is;
  111. HttpURLConnection httpconn = (HttpURLConnection) conn;
  112. if (httpconn.getResponseCode() == 200) {
  113. is = httpconn.getInputStream();
  114. } else {
  115. is = httpconn.getErrorStream();
  116. }
  117. in = new BufferedReader(new InputStreamReader(is));
  118. String line;
  119. while ((line = in.readLine()) != null) {
  120. result += line;
  121. }
  122. } catch (Exception e) {
  123. System.out.println("Send POST Error!" + e);
  124. e.printStackTrace();
  125. }
  126. // Use the finally block to close the output stream, input stream
  127. finally {
  128. try {
  129. if (out != null) {
  130. out.close();
  131. }
  132. if (in != null) {
  133. in.close();
  134. }
  135. } catch (IOException ex) {
  136. ex.printStackTrace();
  137. }
  138. }
  139. return result;
  140. }
  141. }