Signature Method
When using the API, you need to sign your requests. To compute the signature, first concatenate the selected request elements to form a string called the string to sign. Then, you can use the signing key to compute the HMAC hash-based message authentication code of the string to sign.
The following diagram shows the signature computation process:
The signature method is similar to the AWS4 signature method, just replace AWS4 with SD1.
The table below describes the functions shown in the diagram. You need to implement the corresponding code for these functions.
Function | Description |
---|---|
Lowercase() | Converts a string to lowercase. |
Hex() | Base-16 encoded lowercase form. |
SHA256Hash() | Secure Hash Algorithm (SHA) encryption hash function. |
HMAC-SHA256() | Computes HMAC using the SHA256 algorithm and the provided signing key. This is the final signature. |
Trim() | Removes all leading or trailing whitespace. |
UriEncode() | URI encodes each byte, must follow the rules in RFC 3986. |
Signature Steps
Normalize HTTP Request Method
The HTTP method of the request, such as GET or POST, needs to be converted to uppercase if it is not already.
Normalize URL Path
The URI-encoded version of the absolute path component of the URI, starting with a /
after the domain and continuing to the end of the string, or to the question mark character ?
if it contains query string parameters. If the absolute path is empty, use the forward slash character /
.
For example, the URI path of https://api.example.com/api/v1/example
is /api/v1/example=example
and the compiled URI path is /api/v1/example%3Dexample
.
If the absolute path is empty, use the forward slash character /
.
Normalize Query String
URI-encoded query string parameters. You need to URI-encode each name and value separately.
For example, the query string of https://api.example.com/api/v1/example?name=value&name2=value2
is name=value&name2=value2
.
You need to URL-encode each request parameter's name and value according to the RFC3986 rules. The encoding rules are as follows:
- Characters A-Z, a-z, 0-9, and characters
-
_
.
are not encoded - Other characters are encoded as
%XY
, where XY is the hexadecimal representation of the character's ASCII code. For example,#
is encoded as%23
- Spaces are encoded as
%20
, not+
After encoding the parameters and values, connect them with =
and then connect all query strings with &
.
For example, name=!value&name|2=value2
is encoded as name=%21value&name%7C2=value2
.
If the URI does not contain ?
, there is no query string in the request, and you need to set the normalized query string to an empty string, but you still need to include a newline character \n
.
Normalize Request Headers
Convert the request header names to lowercase and trim any leading or trailing whitespace. The values of the request headers should also be trimmed of any leading or trailing whitespace. Concatenate them in the key:value
format. Then sort the request headers by the key
in ascending alphabetical order and connect all headers with \n
.
The signature must include the host
header (for HTTP/1.1
) or the :authority
header (for HTTP/2
) and any x-sd-*
headers. The signature can also include other standard headers, such as content-type
.
The required x-sd-*
headers are as follows:
x-sd-api-version
: API version number, currently supports1.0
x-sd-datetime
: The date and time of the request, must follow the ISO 8601 format, for example,20240101T173850Z
x-sd-instance-id
: Service instance ID, used to identify the service instance, for example,12345678-1234-1234-1234-1234567890ab
For example, the following headers:
Host: api.example.com
X-SD-Api-Version: 1.0
X-SD-Datetime: 20240101T173850Z
X-SD-Instance-Id: 12345678-1234-1234-1234-1234567890ab
After normalization, they become (with \n
as the newline character):
host:api.example.com \n
x-sd-api-version:1.0 \n
x-sd-datetime:20240101T173850Z \n
x-sd-instance-id:12345678-1234-1234-1234-1234567890ab
It is recommended to include all request headers to better verify the legitimacy of the request.
Create a Hash of the Canonical Request
Create a hash of the canonical request using the same algorithm used to create the hash of the payload. The hashed canonical request must be represented as a lowercase hexadecimal string.
Note: When the payload contains files, you do not need to hash the files, just skip the file part.
Concatenate the String to Sign
To create the string to sign, concatenate the following strings separated by newline characters (\n
):
Algorithm \n
RequestDateTime \n
CredentialScope \n
HashedCanonicalRequest
Algorithm
: The signing algorithm, for SHA-256, the algorithm isSD1-HMAC-SHA256
RequestDateTime
: The date and time of the request, this value is the current UTC time in ISO 8601 format, for example,20240101T173850Z
CredentialScope
: The credential scope, formatted asYYYYMMDD/region/service/SD1_request
HashedCanonicalRequest
: The hash of the canonical request calculated in the previous step
region enumeration: sd-region
service enumeration: sd-service
For example:
"SD1-HMAC-SHA256" + "\n" +
"20240101T173850Z" + "\n" +
"20240101/ap-east-1/service/sd1_request" + "\n" +
"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
Create the Signing Key
To create the signing key, use the secret access key as the key for the initial hash operation and perform a series of cryptographic hash operations on the request date, region, and service.
For each step, call the hash function with the required key and data, and the result of each hash function call becomes the input for the next hash function call.
The following example illustrates how to create the SigningKey used in the next part of this process and shows the concatenation and hashing order of the inputs. HMAC-SHA256
is the hash function used to hash the data.
DateKey = HMAC-SHA256("SD1"+"<SecretAccessKey>", "<YYYYMMDD>")
DateRegionKey = HMAC-SHA256(<DateKey>, "<sd-region>")
DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<sd-service>")
SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "sd1_request")
SecretAccessKey
: The secret access keyYYYYMMDD
: The request date, formatted asYYYYMMDD
, for example,20240101
sd-region
: The region, for example,ap-east-1
sd-service
: The service, for example,image-moderation
Calculate the Signature
After creating the signing key, calculate the signature by performing a cryptographic hash operation on the string to sign, using the created signing key as the hash key for this operation.
Signature = Hex(HMAC-SHA256(SigningKey, StringToSign))
Add the Signature to the Request
Add the calculated signature to your request.
Place the signature in the Authorization
header, with no spaces around the commas, for example:
Authorization: SD1-HMAC-SHA256 Credential=012345ABCDEFGHJKLNMOPQRSTU/20240101/ap-east-1/service/sd1_request,
SignedHeaders=host;x-sd-api-version;x-sd-datetime,x-sd-instance-id,
Signature=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef