# Signature Algorithm v2

### Applying for Security Credentials <a href="#applying-for-security-credentials" id="applying-for-security-credentials"></a>

The security credential used in this document is a key, which includes an accessKeyId and an accessKeyPassword.

* AccessKeyId: used to identify the API caller, which is just like a username.
* AccessKeyPassword: used to authenticate the API caller, which is just like a password.
* **You must keep your security credentials private and avoid disclosure; otherwise, your assets may be compromised. If they are disclosed, please disable them as soon as possible.**

You can apply for the security credentials according to [Zenlayer Docs](https://docs.console.zenlayer.com/welcome/platform/team-management/generate-an-api-access-key).

### Signature Calculation Process

Zenlayer Open API v2 supports POST requests. Only `Content-Type: application/json` is supported. The API is called in JSON format.

The following uses querying the list of bare metal instances in the Hong Kong region as an example to describe the steps of signature splicing.

Assuming that your AccessKeyId and AccessKeyPassword are `AKIDz8krbsJ5yKBZQpn74WFkmLPx3` and `Gu5t9xGARNpq86cd98joQYCN3`, respectively, if you want to view the status of the instance in the Hong Kong region whose bare metal instance name is "unnamed", then the request may be:

{% code overflow="wrap" %}

```url
curl -X POST https://console.zenlayer.com/api/v2/bmc \
-H "Authorization: ZC2-HMAC-SHA256 Credential=0D9UtpyKYcHxms5v, SignedHeaders=content-type;host, Signature=efb356c32e55c781e10dc676da59462c22596d82e91c57803666243379555b2f" \
-H "Content-Type: application/json; charset=utf-8" \
-H "X-ZC-Action: DescribeInstances" \
-H "X-ZC-Timestamp: 1673361177" \
-H "X-ZC-Signature-Method: ZC2-HMAC-SHA256" \
-H "X-ZC-Version: 2022-11-20" \
-d '{"pageSize":10,"pageNum":1,"zoneId":"HKG-A"}'
```

{% endcode %}

**Request Headers:**

| Key                   | Explanation                 | Example             |
| --------------------- | --------------------------- | ------------------- |
| X-ZC-Timestamp        | Request timestamp in second | `1673361177`        |
| X-ZC-Version          | API version number          | `2022-11-20`        |
| X-ZC-Action           | Request action              | `DescribeInstances` |
| X-ZC-Signature-Method | Signature method            | `ZC2-HMAC-SHA256`   |
| Authorization         | Authentication process      |                     |

#### 1. Concatenating the CanonicalRequest String

Concatenate the canonical request string (CanonicalRequest) in the following pseudocode format:

{% code overflow="wrap" %}

```
CanonicalRequest = 
  HTTPRequestMethod + '\n' + 
  CanonicalURI + '\n' + 
  CanonicalQueryString + '\n' + 
  CanonicalHeaders + '\n' + 
  SignedHeaders + '\n' + 
  HexEncode(Hash(RequestPayload))
```

{% endcode %}

<table><thead><tr><th width="261">Field Name</th><th>Explanation</th></tr></thead><tbody><tr><td>HTTPRequestMethod</td><td>HTTP request method (POST).</td></tr><tr><td>CanonicalURI</td><td>URI parameter. Slash ("/") is used here.</td></tr><tr><td>CanonicalQueryString</td><td>The query string in the URL of the originating HTTP request. This is always an empty string “” for POST requests.</td></tr><tr><td>CanonicalHeaders</td><td><p>Header information for signature calculation. Custom headers can be added to participate in the signature process to improve the uniqueness and security of the request.<br>Concatenation rules:</p><ol><li>Both the key and value of the header should be converted to lowercase with the leading and trailing spaces removed, so they are concatenated in the format of <strong>key:value</strong> format(<strong>Note:</strong> The last character is '\n');</li><li>If there are multiple headers, they should be sorted in ASCII ascending order by the header keys (lowercase).</li></ol><p>The calculation result in this example is： <code>content-type:application/json; charset=utf-8\nhost:console.zenlayer.com</code></p></td></tr><tr><td>SignedHeaders</td><td><p>Header information for signature calculation, indicating which headers of the request participate in the signature process (they must each individually correspond to the headers in CanonicalHeaders). <code>Content-type</code> and <code>host</code> are required headers.<br>Concatenation rules:</p><ol><li>Both the key and value of the header should be converted to lowercase;</li><li>If there are multiple headers, they should be sorted in ASCII ascending order by the header keys (lowercase) and separated by semicolons (;).</li></ol><p>The value in this example is <code>content-type;host</code>.</p></td></tr><tr><td>HashedRequestPayload</td><td>Hash value of the request payload (i.e., the body, such as <code>{"pageSize":10,"pageNum":1,"zoneId":"HKG-A"}</code> in this example). The pseudocode for calculation is Lowercase(HexEncode(Hash.SHA256(RequestPayload))) by SHA256 hashing the payload of the HTTP request, performing hexadecimal encoding, and finally converting the encoded string to lowercase letters. The calculation result in this example is <code>5f714687ba91c606d503467766151206392474accd137ffea6dce2420b67c29a</code>.</td></tr></tbody></table>

#### 2. Concatenating the String to Be Signed

The string to sign is concatenated as follows:

```
StringToSign =
    Algorithm + \n +           # Signature algorithm, which is ZC2-HMAC-SHA256 for SHA256.
    RequestTimestamp + \n +     # Request timestamp.
    HashedCanonicalRequest 
```

| Field Name             | Explanation                                                                                                                                                                                                                                                                     |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Algorithm              | Signature algorithm, which is currently always `ZC2-HMAC-SHA256`.                                                                                                                                                                                                               |
| RequestTimestamp       | Request timestamp, i.e., the value of the common parameter `X-ZC-Timestamp` in the request header, which is the UNIX timestamp of the current time in seconds, such as `1673361177` in this example.                                                                            |
| HashedCanonicalRequest | Hash value of the CanonicalRequest string concatenated in the steps above. The pseudocode for calculation is Lowercase(HexEncode(Hash.SHA256(CanonicalRequest))). The calculation result in this example is `29396f9dfa0f03820b931e8aa06e20cda197e73285ebd76aceb83f7dede493ee`. |

According to the preceding rules, the string to be signed obtained in the example is as follows:

```
ZC2-HMAC-SHA256
1673361177
29396f9dfa0f03820b931e8aa06e20cda197e73285ebd76aceb83f7dede493ee
```

#### 3. Calculating the Signature Based on AK and StringToSign

Calculate the derived signature key with the following pseudocode:

```
Signature = HexEncode(HMAC_SHA256(AccessKeyPassword, StringToSign))
```

| Field Name        | Explanation                                                        |
| ----------------- | ------------------------------------------------------------------ |
| AccessKeyPassword | The original AccessKeyPassword, i.e., `Gu5t9xGARNpq86cd98joQYCN3`. |
| StringToSign      | The result obtained in Step 2.                                     |

#### **4.** Concatenating the Authorization

The Authorization is concatenated as follows:

```
Authorization =
    Algorithm + ' ' +
    'Credential=' + AccessKeyId +  ', ' +
    'SignedHeaders=' + SignedHeaders + ', ' +
    'Signature=' + Signature
```

| Field Name    | Explanation                                                                                                                    |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Algorithm     | Signature algorithm, which is always `ZC2-HMAC-SHA256`.                                                                        |
| AccessKeyId   | The AccessKeyId in the key pair, i.e., `0D9UtpyKYcHxms5v`.                                                                     |
| SignedHeaders | Header information for signature calculation (see above), such as `content-type;host` in this example.                         |
| Signature     | Signature value. The calculation result in this example is `efb356c32e55c781e10dc676da59462c22596d82e91c57803666243379555b2f`. |
