Key Management Service (KMS) uses a request signature to verify the identity of an API caller. This ensures data security when you call API operations.
Security verification
Security verification is based on the client key that is bound to the application access point (AAP) of KMS and is used to perform the following operations by using asymmetric signature algorithms:
- Verifies the identity of the user who sends the API request.
Before a user sends a request, the user must specify the client key that is bound to the AAP to generate a signature. The identity of the user is identified based on the client key on the server. This way, access permissions can be managed in an efficient manner.
- Checks whether the API request is tampered with during transmission.
The server verifies the signature of the received request. If the request is tampered with during transmission, the request cannot pass signature verification.
The following process describes the security verification for an API request:
- The client generates a string-to-sign based on the HTTP header and body of the API request.
- The client signs the string that is generated in Step 1 by using the private key of the client key that is bound to the AAP to generate a signature for the API request. The PrivateKeyData parameter specifies the private key.
- The client sends the API request data and the signature to the server.
- After the server receives the request, the server uses the public key of the client key to verify the signature. If the signature passes the verification, the API request is accepted. If the signature fails the verification, the API request is rejected. Note The server obtains the public key of the client key that is bound to the AAP in the backend.
Signature process
Authorization = "TOKEN" + " " + Signature
A signature is generated by using the private key of the client key that is bound to the AAP to sign the API request. The following process describes how to generate a signature:
- Obtain the client key that is bound to the AAP. The private key of the client key is required to generate a signature for the API request. You can use an existing client key or create a client key. Make sure that the client key is in the enabled state.
- Generate a string-to-sign for the API request. The string-to-sign contains information, such as the HTTP request method, HTTP request headers, and HTTP request body. The string-to-sign is in the following format:
SignString = HTTP-METHOD + "\n" + CONTENT-SHA256 + "\n" + CONTENT-TYPE + "\n" + DATE + "\n" + CanonicalizedKMSHeaders + "\n" + CanonicalizedResource
\n
is a line feed, and the plus sign(+)
is a string concatenation operator. The following table describes other headers.Header Description Example HTTP-METHOD
The HTTP request method. PUT, GET, and POST CONTENT-SHA256
The SHA-256 hash value of the request content. AE71057543002AD513AB88D78509A1214192C09F20302C4BF8F59B7EB565**** CONTENT-TYPE
The type of the HTTP request body. application/x-protobuf DATE
The standard timestamp header of the HTTP request. This header follows the RFC 1123 format. The time is in Coordinated Universal Time (UTC). Mon, 27 Sep 2021 11:47:26 GMT CanonicalizedKMSHeaders
The string that consists of the custom headers prefixed with x-kms
in the HTTP request.x-kms-acccesskeyid:KAAP.9c84ad54-d3c5-47c3-b0e7-7c26d509****\nx-kms-apiname:Encrypt\nx-kms-apiversion:dkms-gcs-0.2\nx-kms-signaturemethod:RSA_PKCS1_SHA_256 CanonicalizedResource The value is fixed as /
./ If an HTTP request does not have a body, theCONTENT-SHA256
andCONTENT-TYPE
headers are empty strings. The string-to-sign is in the following format:SignString = HTTP-METHOD + "\n" + "\n" + "\n" + DATE + "\n" + CanonicalizedKMSHeaders + "\n" + CanonicalizedResource
KMS API introduces custom headers that are prefixed withx-kms
. If you specify a custom header in an API request, the value of this header is used to calculate a signature. The following process describes how to generate theCanonicalizedKMSHeaders
header:- Convert all HTTP header names that are prefixed with
x-kms
to lowercase. - Sort all custom request headers in alphabetical order.
- Delete all spaces on each side of the delimiter between each header and the value of the header. For example:
CONTENT-TYPE : application/x-protobuf
is converted toCONTENT-TYPE:application/x-protobuf
. - Separate all headers and the values of the headers with the
\n
delimiter to obtain the CanonicalizedKMSHeaders header.
- Convert all HTTP header names that are prefixed with
- Generate a signature for the request. KMS API supports only the signature algorithm
RSA_PKCS1_SHA_256
. You can generate a signature by using the following formula:Signature=Base64(RSA_PKCS1_SHA_256(SignString, AAP_KEY))
When you generate a signature, take note of the following items:
- You must encode the value that is generated by the signature algorithm in Base64.
- You must use the RSASSA-PKCS1-v1_5 signature algorithm to sign the string-to-sign. For more information about the RSASSA-PKCS1-v1_5 signature algorithm, visit RFC 3447.
- After you generate the signature, add the signature to the Authorization header.
- The string-to-sign must be encoded in
UTF-8
. If the string-to-sign contains Chinese characters, you must encode the string inUTF-8
before you calculate a signature. - The
CONTENT-SHA256
andCONTENT-TYPE
headers are not required in the request. If theCONTENT-SHA256
andCONTENT-TYPE
headers are empty, you must replace the values of the headers with line feeds\n
.
Signature example
The following example shows how an API request is signed. In this example, the Encrypt operation is used.
- Client key that is bound to the AAP
{ "KeyId": "KAAP.9c84ad54-d3c5-47c3-b0e7-7c26d509****", "PrivateKeyData": "MIIJqwIB****UcQ==" }
- Encryption parameters of the Encrypt operation
keyId = "1234abcd-12ab-34cd-56ef-12345678****" plaintext = "plain text"
The following process shows the signature process:
- Construct the following HTTP request based on the definition of KMS API.
POST / HTTP/1.1 Date: Mon, 27 Sep 2021 11:47:26 GMT Host: kst-xxxx.cryptoservice.kms.aliyuncs.com Accept: application/x-protobuf Content-SHA256: AE71057543002AD513AB88D78509A1214192C09F20302C4BF8F59B7EB565**** Content-Length: 40 Content-Type: application/x-protobuf x-kms-acccesskeyid: KAAP.9c84ad54-d3c5-47c3-b0e7-7c26d509**** x-kms-apiversion: dkms-gcs-0.2 x-kms-apiname: Encrypt x-kms-signaturemethod: RSA_PKCS1_SHA_256 <The encryption parameters are serialized into byte streams in the Protocol Buffers format.>
The byte streams in the Protocol Buffers format are used as the request body. The value of the
Content-Type
header in the request is set toapplication/x-protobuf
. The value of theContent-SHA256
header is set to the hex string in uppercase that is generated after the request body is calculated by using SHA-256. - Construct a string-to-sign.
POST\nAE71057543002AD513AB88D78509A1214192C09F20302C4BF8F59B7EB56551E2\napplication/x-protobuf\nMon, 27 Sep 2021 11:47:26 GMT\nx-kms-acccesskeyid:KAAP.9c84ad54-xxxx-xxxx-xxxx-7c26d509a55d\nx-kms-apiname:Encrypt\nx-kms-apiversion:dkms-gcs-0.2\nx-kms-signaturemethod:RSA_PKCS1_SHA_256\n/
- Use the private key of the client key to generate a signature, and encode the signature in Base64.
BPwBSB9NkxxuepqJ2zRtLT8jgv0FIAELJI2U79k8OPO7M7Y18Sz6+njTSwYWeIIQpJIJKx+mGBl/aR9opPbfQ+PhH+78rIPLJYNAJRvvaSUW/cRr4BMc1ByRXvuBmIcI81MQGutuU8uLnQYh9AURdklpqcW3ODz5OfsbuuxTGV17COoSO10tW3ltADumaMczFGTM0qCYi/pyh8p8i/gpwC3EXo540n5mqEmLexYIWb5/Fo+VonqZxZ3UuhZPw3vQ8uvqMGqvvw0xxKsblGuEdNSHcy/GYGRTFYugwOojZxd7TpADTqys+7SYaBWT38HnQLcH04DeD5rKkhRK7au8HQ==
- Send the HTTP request that contains the signature.
POST / HTTP/1.1 Date: Mon, 27 Sep 2021 11:47:26 GMT Host: kst-xxxx.cryptoservice.kms.aliyuncs.com Accept: application/x-protobuf Content-SHA256: AE71057543002AD513AB88D78509A1214192C09F20302C4BF8F59B7EB565**** Content-Length: 40 Content-Type: application/x-protobuf x-kms-acccesskeyid: KAAP.9c84ad54-d3c5-47c3-b0e7-7c26d509**** x-kms-apiversion: dkms-gcs-0.2 x-kms-apiname: Encrypt x-kms-signaturemethod: RSA_PKCS1_SHA_256 Authorization: TOKEN BPwBSB9NkxxuepqJ2zRtLT8jgv0FIAELJI2U79k8OPO7M7Y18Sz6+njTSwYWeIIQpJIJKx+mGBl/aR9opPbfQ+PhH+78rIPLJYNAJRvvaSUW/cRr4BMc1ByRXvuBmIcI81MQGutuU8uLnQYh9AURdklpqcW3ODz5OfsbuuxTGV17COoSO10tW3ltADumaMczFGTM0qCYi/pyh8p8i/gpwC3EXo540n5mqEmLexYIWb5/Fo+VonqZxZ3UuhZPw3vQ8uvqMGqvvw0xxKsblGuEdNSHcy/GYGRTFYugwOojZxd7TpADTqys+7SYaBWT38HnQLcH04DeD5rKkhRK7au8HQ== <The encryption parameters are serialized to byte streams in the Protocol Buffers format.>