Skip to content

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: signature method image

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.

FunctionDescription
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 supports 1.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 is SD1-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 as YYYYMMDD/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 key
  • YYYYMMDD: The request date, formatted as YYYYMMDD, 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