Signature Process
This topic describes how to generate a signature.
- Step 1: Adding New Request Headers to the Request Header List
- Step 2: Calculating the SHA-256 Value of the Request Body
- Step 3: Calculating CanonicalRequest
- Step 4: Calculating StringToSign
- Step 5: Calculating SigningKey
- Step 6: Calculating Signature
- Step7: Generating Signature Information for Requests
The signature result varies with time. In the following example, the value of X-Sdk-Date is 20181101T081630Z. If the signature result of the code is the same as the sample result, do not obtain the value of X-Sdk-Date based on the current time, the value is fixed to 20181101T081630Z. In this way, the signature results can be compared. After the test is complete, change the value of X-Sdk-Date based on the current time.
Adding New Request Headers to the Request Header List
|
Request Header |
Description |
Example |
|---|---|---|
|
Host |
Domain name and port number in the URL. The format is host:port (that is, domain name: port number).
NOTE:
If any of the following conditions is met, delete :port and reserve the host:
|
|
|
X-Sdk-Date |
Character string generated based on the current UTC time (Beijing time - 8 hours). The format is yyyyMMddTHHmmssZ. YYYY is the year, MM is the month, dd is the day, T is the fixed character, HH is the 24-hour clock, mm is the minute, ss is the second, and Z is the fixed character. For example, on 2018-11-01 16:16:30 (Beijing time), the generated X-Sdk-Date value is 20181101T081630Z. |
20181101T081630Z |
The request header list generated based on the example is as follows:
Host: dis.${region}.myhuaweicloud.com
X-Sdk-Date: 20181101T081630Z
Calculating the SHA-256 Value of the Request Body
String calculateContentHash=sha256(content)
The value is obtained by calculating the SHA-256 value of the request body content.
If there is no request body (that is, the value of content is null), the value of calculateContentHash is fixed to e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.
The following is an example:
{"stream_name":"test2","records":[{"data":"aGVsbG8gd29ybGQu","partition_id":"","explicit_hash_key":"","partition_key":"0"}]},
The calculated calculateContentHash result is as follows:
af22378806bf4e69f5f1667877906e6ead78080cd859b4988ea6714dba6d1e02
Calculating CanonicalRequest
String CanonicalRequest =
HTTPRequestMethod + '\n' +
CanonicalURI + '\n' +
CanonicalQueryString + '\n' +
CanonicalHeaders + '\n' +
SignedHeaders + '\n' +
calculateContentHash
|
Parameter |
Description |
Example |
|---|---|---|
|
HTTPRequestMethod |
HTTP request type. |
POST |
|
CanonicalURI |
Resource path between a URL domain name port and a parameter.
NOTICE:
If the resource path does not end with a slash (/), add / at the end. |
|
|
CanonicalQueryString |
Character string generated after the query parameters in the URL are sorted in lexicographical order. The format is as follows: CanonicalQueryEntry0 + "&" + CanonicalQueryEntry1 + ... If there is no parameter, the value is an empty character string.
NOTE:
The format of CanonicalQueryEntry is UrlEncode(QueryName) + '=' + UrlEncode(QueryValue). That is, URL encoding is performed on the request header and value, and the equal sign (=) is used to connect the request header and value. |
partition-id=0&stream-name=test2 |
|
CanonicalHeaders |
Character string generated after the request headers (case insensitive) are sorted in lexicographical order. The format is as follows: CanonicalHeadersEntry0 + CanonicalHeadersEntry1 + ...
NOTE:
The format of CanonicalHeadersEntry is Lowercase(HeaderName) + ':' + Trimall(HeaderValue) + '\n' |
host:dis.${region}.myhuaweicloud.com:20004\nx-sdk-date:20181101T081630Z\n |
|
SignedHeaders |
Character string generated after all the request headers are converted to lowercase letters and are sorted in lexicographical order. The format is Lowercase(HeaderName0) + ';' + Lowercase(HeaderName1) + ";" + ...
NOTE:
Convert all request header names to lowercase letters, sort them in lexicographical order, and use semicolons (;) to separate multiple lowercase request headers. |
host;x-sdk-date |
|
calculateContentHash |
SHA-256 value of the request body. For details, see Calculating the SHA-256 Value of the Request Body. |
af22378806bf4e69f5f1667877906e6ead78080cd859b4988ea6714dba6d1e02 |
The CanonicalRequest result calculated based on the example is as follows: (\n is displayed as a newline character.)
POST
/v2/d575b0b740e54221aeb9a165653b103d/records/
partition-id=0&stream-name=test2
host:dis.${region}.myhuaweicloud.com
x-sdk-date:20181101T081630Z
host;x-sdk-date
af22378806bf4e69f5f1667877906e6ead78080cd859b4988ea6714dba6d1e02
If \n is not displayed as a newline, the format is as follows:
POST\n/v2/d575b0b740e54221aeb9a165653b103d/records/\npartition-id=0&stream-name=test2\nhost:dis.${region}.myhuaweicloud.com\nx-sdk-date:20181101T081630Z\n\nhost;x-sdk-date\naf22378806bf4e69f5f1667877906e6ead78080cd859b4988ea6714dba6d1e02
Calculating StringToSign
String StringToSign =
Algorithm + '\n' +
RequestDate + '\n' +
CredentialScope + '\n' +
HashedCanonicalRequest))
|
Parameter |
Description |
Example |
|---|---|---|
|
Algorithm |
Encryption algorithm. The value is fixed to SDK-HMAC-SHA256. |
SDK-HMAC-SHA256 |
|
RequestDate |
Value of X-Sdk-Date. |
20181101T081630Z |
|
CredentialScope |
Authentication scope. The format is date/region/service/terminationString.
|
20181101/${region}/dis/sdk_request |
|
HashedCanonicalRequest |
SHA-256 value of CanonicalRequest calculated in Calculating CanonicalRequest. |
bf0eb8735b561a700b85b1142eb61df06569dffcd1088a7dda539e2ee6497809 |
The following is a sample result:
StringToSign=SDK-HMAC-SHA256\n20181101T081630Z\n20181101/${region}/dis/sdk_request\n548470a57f61f5841c6869cd51164be0da033c14a874ff7a498593a4ae202b41
Calculating SigningKey
SigningKey is a byte array calculated using the HmacSHA256 algorithm. The method is as follows:
kSecret = Bytes("SDK"+sk)
kDate = HmacSHA256(kSecret, Date)
kRegion = HmacSHA256(kDate, Region)
kService = HmacSHA256(kRegion, Service)
SigningKey = HmacSHA256(kService, "sdk_request")
The HmacSHA256 algorithm uses a key (in the format of byte array) and a message (in the format of character string) as input to generate a message digest (in the format of byte array) as the output. The result of HmacSHA256 is a byte array. To intuitively show the result of each step and facilitate verification, the following example shows that the result of each step is a hexadecimal character string, that is, HexEncode(Result), note that the calculation process is still a byte array rather than the value after HexEncode.
|
Parameter |
Description |
Example (Actual Value After HexEncode) |
|---|---|---|
|
kSecret |
"SDK"+sk, which is converted into a byte array as the initial key. |
53444b76524e77474d643932506c697479494f3364614473656f53396863694c39784b534b6b42694a3434 |
|
kDate |
HmacSHA256 value of kSecret and Date (the Date field of X-Sdk-Date). |
305758792674e5cfec8609daf3725e37367d8479ee824d2914db63004b5211b2 |
|
kRegion |
HmacSHA256 value of kDate and Region. |
c56298c0270a63bb57779cdfe02d41b55393f8b61bf4c793b06866c14f9b28e7 |
|
kService |
HmacSHA256 value of kRegion and Service. |
ed5246fb17c384c46000ba85a7c788e3e18c5e0323240f9bff6a1308df9179e8 |
|
SigningKey |
HmacSHA256 value of kService and sdk_request. |
1ea4929f7f18601abb9af0aaa9dc46eb0b6bda7b1de20d2a152dbe76e05dffad |
The StringToSign result is a byte array and cannot be directly represented in the document. Therefore, StringToSign is represented by a hexadecimal string (that is, HexEncode(StringToSign), which is the following character string:
1ea4929f7f18601abb9af0aaa9dc46eb0b6bda7b1de20d2a152dbe76e05dffad
The character string is not the result of StringToSign but the result of HexEncode(StringToSign) for the convenience of the user to check whether the result is correct. When Signature is calculated in the next step, the value of StringToSign must be transferred.
SigningKey is related only to sk, date, region, and service. When the four parameters remain unchanged, the value of SigningKey is fixed. For better performance, the SigningKey result can be cached and used repeatedly.
Calculating Signature
String Signature = HexEncode(HmacSHA256(SigningKey, StringToSign))
Parameters required for constructing Signature
The value of String Signature is a hexadecimal character string converted from the HmacSHA256 value of SigningKey and StringToSign.
The Signature result calculated based on the example is as follows:
8df520f285a18b7b101fc0d6507de03c4078460c65baa289ffa49ca718e9190b
Generating Signature Information for Requests
After the following value is added to a request header, the signing is completed:
Authorization: SDK-HMAC-SHA256 Credential=ak/CredentialScope, SignedHeaders=SignedHeaders, Signature=signature
- ak: user AK.
- CredentialScope: the authentication range used in Calculating StringToSign.
Example: 20181101/${region}/dis/sdk_request
- SignedHeaders: SignedHeaders used in Calculating CanonicalRequest.
Sample: host;x-sdk-date
- Signature: the signature obtained in Calculating Signature.
Example: 8df520f285a18b7b101fc0d6507de03c4078460c65baa289ffa49ca718e9190b
The signature request header calculated based on the example is as follows:
Authorization: SDK-HMAC-SHA256 Credential=DJZN5UEQSODCWJ7NGOMC/20181101/${region}/dis/sdk_request, SignedHeaders=host;x-sdk-date, Signature=8df520f285a18b7b101fc0d6507de03c4078460c65baa289ffa49ca718e9190b
Problem Analysis
- If the signature is correct but the AK or project ID does not exist, the server returns the following information:
441 : Invalid AccessKey header. [Invaild ak.]
Handling method:
Ensure that the AK is correct by referring to AK/SK-based Authentication.
Ensure that the Project ID is correct by referring to Obtaining a Project ID.
- If the signature logic or SK is incorrect, the server returns the following information:
441 : Invalid authorization request.
Handling method:
Use the sample parameters to verify the signature process and compare the verification result with the sample result to ensure that the signature process is correct.
- If the region is incorrect (for example, send a request for a DIS address in CN South ${region} when the current region is CN North1 ${region}, the server returns the following information:
441 : Invalid Region header. [${region}]Handling method:
Ensure that the region maps the DIS address by referring to Obtaining a Project ID.
- If the value of X-Sdk-Date is more than 15 minutes later than the standard time, the server returns the following information:
441 : Invalid X-Sdk-Date header
Handling method:
Adjust the client time to the standard time of the corresponding time zone.
Last Article: Authentication of Signature in a Header
Next Article: Getting Started
Did this article solve your problem?
Thank you for your score!Your feedback would help us improve the website.