Last Updated on : 2024-06-19 02:57:45download
When you make requests to APIs, you must provide a signature to verify your identity and ensure data security. This topic describes how to generate a signature in a request.
The integration of cloud development SDKs can relieve you from the tedious process of generating API signatures. For more information, see Service SDKs.
HMAC-SHA256 is used in API services to create a message digest. Different signature algorithms are applied to token management API requests and general API requests, as described in the following table.
API type | Token management API | General business API |
---|---|---|
Scope of application | Requests that are made to get or refresh tokens | Requests that are made to manage business rather than tokens. |
Signature algorithm |
str = client_id + t + nonce + stringToSign sign = HMAC-SHA256(str, secret).toUpperCase() |
str = client_id + access_token + t + nonce + stringToSign sign = HMAC-SHA256(str, secret).toUpperCase() |
Field description |
|
|
Field description | Concatenate the value of client_id, the 13-digit standard timestamp (t) of the specified request, nonce, and stringToSign to create a string named as str. Use HMAC-SHA256 to create a hash digest value based on the string str and the value of the secret. Capitalize all letters of the hash digest value to get a signature. |
Different from token management API requests, in the signature algorithm for general API requests, access_token
is additionally concatenated to generate the string str
.
stringToSign
signature stringstringToSign
is created in the following structure:
String stringToSign=
HTTPMethod + "\n" +
Content-SHA256 + "\n" +
Optional_Signature_key + "\n" +
URL
This structure consists of the following four parts:
You can concatenate the strings of these four parts with line-feed characters (\n) to create a string-to-sign named as stringToSign
.
HTTPMethod
represents an API method, such as GET
, POST
, PUT
, and DELETE
.
Content-SHA256
represents the SHA256 value of a request body. SHA256 is calculated only when the body is not a form.
Calculation:
String content-SHA256 = SHA256(bodyStream.getbytes("UTF-8")); // bodyStream is a byte array.
An empty body is still encrypted into e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
.
Optional_Signature_key
represents the string in which all request headers involved in the signature calculation are concatenated with line-feed characters (\n) as described in Request Structure. Each request header is a key-value pair. For example:
The request parameters are as follows:
client_id: 1KAD46OrT9HafiKd****
sign: C5EFD19AD45E33A060C0BE47AEF65D975D54B2D70CBAA7A1ACA1A7D0E5C0****
sign_method: HMAC-SHA256
t: 1588925778000
access_token: 3f4eda2bdec17232f67c0b188af3****
nonce: 5138cc3a9033d69856923fd07b49****
...
To improve data security, add two custom fields area_id
and req_id
to the signature calculation.
area_id: 29a33e8796834b1****
req_id: 8afdb70ab2ed11eb85290242ac13****
The new request structure as follows:
client_id: 1KAD46OrT9HafiKd****
sign: C5EFD19AD45E33A060C0BE47AEF65D975D54B2D70CBAA7A1ACA1A7D0E5C0****
sign_method: HMAC-SHA256
t: 1588925778000
access_token: 3f4eda2bdec17232f67c0b188af3****
nonce: 5138cc3a9033d69856923fd07b49****
...
// Two request headers are added
Signature-Headers: area_id:req_id
area_id: 29a33e8796834b1**** // Subject to your customization
req_id: 8afdb70ab2ed11eb85290242ac13**** // Subject to your customization
All request header fields involved are concatenated with colons (:
). As shown in the preceding code block, area_id:req_id
is generated as the value of Signature-Headers
.
Then, concatenate all key-value pairs included in Signature-Headers
to generate the value of Optional_Signature_key
in the following structure:
String Optional_Signature_key =
Signature-Headers-Key1 + ":" + Signature-Headers-Value1 + "\n" +
Signature-Headers-Key2 + ":" + Signature-Headers-Value2 + "\n" +
...
Signature-Headers-KeyN + ":" + Signature-Headers-ValueN + "\n"
In this example, the following value of Optional_Signature_key
is obtained:
String Optional_Signature_key =
area_id + ":" + 29a33e8796834b1**** + "\n" +
req_id + ":" + 8afdb70ab2ed11eb85290242ac13**** + "\n"
A URL represents the request path into which a request path and form parameters are concatenated.
Concatenate URLs: Sort form parameters by keys in alphabetically ascending order and concatenated in the following way. If query parameters or form parameters are empty, set the URL to the request path that is not suffixed with a question mark (?
).
String url =
Path +
"?" +
Key1 + "=" + Value1 +
"&" + Key2 + "=" + Value2 +
"&" + Key3 +
...
"&" + KeyN + "=" + ValueN
For example:
String url = /v1.0/iot-03/devices/87707085bcddc23a5fa3/logs?end_time=1657263936000&event_types=1&start_time=1657160836000
Sort parameters in alphabetically ascending order. If multiple parameters have the same initial letter, sort these parameters by their second letter alphabetically. This way, letters are sequentially compared among different parameters until the parameters can be sorted as expected.
Take the following parameters as an example:
start_time
=1657160836000end_time
=1657263936000event_types
=1They are sorted in the following alphabetical order:
end_time
=1657263936000
event_types
=1
start_time
=1657160836000
In these parameters, end_time
and event_types
have the same initial letter, and the second letter n
of end_time
comes earlier in the alphabet than the second letter v
of event_types
. Therefore, end_time
is followed by event_types
.
The first letter of end_time
and event_types
comes earlier in the alphabet than the first letter of start_time
. As a result, end_time
and event_types
are followed by start_time
.
In the following example, make an API request to get a token. Set grant_type
to 1
and leave the body parameter empty.
GET:/v1.0/token?grant_type=1
The request header structure is as follows:
Parameter | Value |
---|---|
method | GET |
client_id | 1KAD46OrT9HafiKdsXeg |
secret | 4OHBOnWOqaEC1mWXOpVL3yV50s0qGSRC |
t | 1588925778000 |
sign_method | HMAC-SHA256 |
nonce | 5138cc3a9033d69856923fd07b491173 |
Signature-Headers | area_id:call_id |
area_id (Customized and used in signature calculation) | 29a33e8796834b1efa6 |
call_id (Customized and used in signature calculation) | 8afdb70ab2ed11eb85290242ac130003 |
stringToSign
Generate the string-to-sign stringToSign
in the following structure:
GET
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
area_id:29a33e8796834b1efa6
call_id:8afdb70ab2ed11eb85290242ac130003
/v1.0/token?grant_type=1
The structure is described as follows:
After stringToSign
is generated, you can use it to create the string str
:
1KAD46OrT9HafiKdsXeg15889257780005138cc3a9033d69856923fd07b491173GET
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
area_id:29a33e8796834b1efa6
call_id:8afdb70ab2ed11eb85290242ac130003
/v1.0/token?grant_type=1
The structure is described as follows:
Hash digest value:
HMAC-SHA256(1KAD46OrT9HafiKdsXeg15889257780005138cc3a9033d69856923fd07b491173GET
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
area_id:29a33e8796834b1efa6
call_id:8afdb70ab2ed11eb85290242ac130003
/v1.0/token?grant_type=1,4OHBOnWOqaEC1mWXOpVL3yV50s0qGSRC)
Create a hash digest value and encode the hash digest value into a new string:
9e48a3e93b302eeecc803c7241985d0a34eb944f40fb573c7b5c2a82158af13e
Capitalize all letters of the new string:
9E48A3E93B302EEECC803C7241985D0A34EB944F40FB573C7B5C2A82158AF13E
In the following example, make an API request to get a list of users. Set schema
to apps
and leave the body parameter empty.
Parameter | Value |
---|---|
URL | /v2.0/apps/schema/users |
method | GET |
client_id | 1KAD46OrT9HafiKdsXeg |
secret | 4OHBOnWOqaEC1mWXOpVL3yV50s0qGSRC |
t | 1588925778000 |
access_token | 3f4eda2bdec17232f67c0b188af3eec1 |
sign_method | HMAC-SHA256 |
nonce | 5138cc3a9033d69856923fd07b491173 |
Signature-Headers | area_id:call_id |
area_id (Customized and used in signature calculation) | 29a33e8796834b1efa6 |
call_id (Customized and used in signature calculation) | 8afdb70ab2ed11eb85290242ac130003 |
page_no | 1 |
page_size | 50 |
stringToSign
Generate the string-to-sign stringToSign
in the following structure:
GET
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
area_id:29a33e8796834b1efa6
call_id:8afdb70ab2ed11eb85290242ac130003
/v2.0/apps/schema/users?page_no=1&page_size=50
The structure is described as follows:
After stringToSign
is generated, you can use it to create the string str
:
1KAD46OrT9HafiKdsXeg3f4eda2bdec17232f67c0b188af3eec115889257780005138cc3a9033d69856923fd07b491173GET
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
area_id:29a33e8796834b1efa6
call_id:8afdb70ab2ed11eb85290242ac130003
/v2.0/apps/schema/users?page_no=1&page_size=50
The structure is described as follows:
Hash digest value:
HMAC-SHA256(1KAD46OrT9HafiKdsXeg3f4eda2bdec17232f67c0b188af3eec115889257780005138cc3a9033d69856923fd07b491173GET
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
area_id:29a33e8796834b1efa6
call_id:8afdb70ab2ed11eb85290242ac130003
/v2.0/apps/schema/users?page_no=1&page_size=50,4OHBOnWOqaEC1mWXOpVL3yV50s0qGSRC)
Create a hash digest value and encode the hash digest value into a new string:
ae4481c692aa80b25f3a7e12c3a5fd9bbf6251539dd78e565a1a72a508a88784
Capitalize all letters of the new string:
AE4481C692AA80B25F3A7E12C3A5FD9BBF6251539DD78E565A1A72A508A88784
Download the sample code for Java.
Download the sample code for Golang.
Download the sample code for Node.js.
/**
Run the code online with this jsfiddle. Dependent upon an open source js library calledhttp://code.google.com/p/crypto-js/.
**/
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/enc-base64.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/hmac-sha256.min.js"></script>
<script>
var hash = CryptoJS.HmacSHA256("str", "secret");
var hashInBase64 = hash.toString().toUpperCase();
document.write(hashInBase64);
</script>
/**
PHP has built-in methods for hash_hmac (PHP 5) and base64_encode (PHP 4, PHP 5) resulting in no outside dependencies. Say what you want about PHP but they have the cleanest code for this example.
**/
$s = strtoupper(hash_hmac("sha256", "str", 'secret'));
echo var_dump($s);
using System;
using System.Security.Cryptography;
namespace Test
{
public class MyHmac
{
public static string Encrypt(string str, string secret)
{
secret = secret ?? "";
var encoding = new System.Text.UTF8Encoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(str);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < hashmessage.Length; i++)
{
builder.Append(hashmessage[i].ToString("x2"));
}
return builder.ToString().ToUpper();
}
}
}
}
During local development, you can test API requests with Postman to verify the encrypted signature. For more information, see Verify Signature Result.
stringToSign
?This depends on the structure of stringToSign
. stringToSign
consists of HTTPMethod
, Content-SHA256
, Headers
, and URL
, concatenated with a line-feed character (\n) in between. The structure is as follows:
String stringToSign=
HTTPMethod + "\n" +
Content-SHA256 + "\n" +
Headers + "\n" +
URL
The following example shows how to calculate Headers
:
String Headers =
HeaderKey1 + ":" + HeaderValue1 + "\n" +
HeaderKey2 + ":" + HeaderValue2 + "\n" +
...
HeaderKeyN + ":" + HeaderValueN + "\n"
Therefore, the Headers
string is followed by two line-feed characters (\n) that result in a blank line.
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback