This topic describes how to import external key materials and delete the external key materials imported into a CMK.

CMK overview

Customer master keys (CMKs) are basic resources of KMS. CMKs are composed of key IDs, basic metadata (such as key state) and key materials used to encrypt and decrypt data. KMS generates key materials when you call the CreateKey operation. You can choose to create a key from external key materials. In this case, KMS does not generate key materials for the CMK you create and you can import your own key materials to the CMK. You can call the DescribeKey operation to view the source of key materials. When the Origin value in the KeyMetadata is Aliyun_KMS, the key material was generated by KMS and the corresponding key is a normal key. If the Origin value is EXTERNAL, the key material was imported from an external source and the corresponding key is an external key.

Precautions

When you select an external key material source and use the key material you imported, take note of the following points:

  • You must make sure that qualified random sources are used to generate key materials.
  • You must ensure the reliability of the key materials.
    • KMS ensures the high availability of imported key materials, but cannot ensure that the imported key material has the same reliability as the key material generated by KMS.
    • You can directly call the DeleteKeyMaterial operation to delete the imported key material. Alternatively, you can set an expiration time to automatically delete the imported key material after it expires (without deleting CMKs). The key material generated by KMS cannot be directly deleted. Instead, you can call the ScheduleKeyDeletion operation to delete the key material along with CMK after 7 to 30 days.
    • After you delete the imported key material, you can re-import the same key material to make the relevant CMK available again. Therefore, you need to save a copy of the key material.
  • Each CMK can only have one imported key material. After you import the key material to a CMK, this CMK is bound to this key material. Even if the key material expires or is deleted, you cannot import any other key material into the CMK. If you need to rotate a CMK that uses the external key material, you must create a new CMK and then import new key material.
  • CMKs are independent. When you use one CMK to encrypt data, you cannot use another CMK to decrypt the data, even if these CMKs use the same key material.
  • You can only import 256-bit symmetric keys as key materials.

Import key materials

  1. Create an external key.

    First, you must create an external key.

    To do this, set Key Material Source to External on the Create Key page of the KMS console, or call the CreateKey operation and set Origin to EXTERNAL. By choosing to create an external key, you acknowledge that you have read and understood the Precautions and Import key materials sections of this topic.

    Example

    aliyuncli kms CreateKey --Origin EXTERNAL --Description "External key"
  2. Obtain key material import parameters.

    After you create an external key and before you import the key material, you must obtain the key material import parameters.

    You can obtain the key material import parameters through the console or by calling the GetParametersForImport operation. The key material import parameters include a public key used to encrypt the key material and an import token.

    Example

    aliyuncli kms GetParametersForImport --KeyId 1339cb7d-54d3-47e0-b595-c7d3dba82b6f --WrappingAlgorithm RSAES_OAEP_SHA_1 --WrappingKeySpec RSA_2048
  3. Import key materials.

    You can import key materials for external keys that do not yet have key materials, re-import key materials that have expired or been deleted, or reset the key material expiration time. The import token is bound to the public key used to encrypt key material. A single token can only be used to import the key material for the CMK specified at the time of generation. An import token is valid for 24 hours and can be used multiple times during this period. After the token expires, you must obtain a new import token and public encryption key.

    • First, use the public encryption key to encrypt the key material. The public encryption key is a 2048-bit RSA public key. The encryption algorithm used must be consistent with that specified when obtaining the key material import parameters. Because the public encryption key returned when you call the operation is Base64 encoded, you must first perform Base64 decoding before using the public encryption key. KMS supports the following encryption algorithms: RSAES_OAEP_SHA_1, RSAES_OAEP_SHA_256, and RSAES_PKCS1_V1_5.
    • After encryption, you must perform Base64 encoding on the encrypted key material and then import the key material along with the import token to KMS as GenerateDataKey parameters.

    Example

    aliyuncli kms ImportKeyMaterial --KeyId 1339cb7d-54d3-47e0-b595-c7d3dba82b6f --EncryptedKeyMaterial xxx --ImportToken xxxx

Delete key materials

  • After importing key materials, you can use external keys just like normal keys. External keys differ from normal keys because their key material can expire or be manually deleted. After the key material expires or is deleted, the key will no longer function and ciphertext data encrypted using this key cannot be decrypted before you re-import the same key material.
  • If a key enters the PendingDeletion state after its key material expires or is deleted, the key state does not change. Otherwise, the key state changes to PendingImport.
  • You can use the console or call the DeleteKeyMaterial operation to delete the key material.

Example

aliyuncli kms DeleteKeyMaterial --KeyId xxxx            

Examples

Use OPENSSL to encrypt and upload key material

  • Create an external key.
  • Generate the key material. The key material must be a 256-bit symmetric key. In this example, OPENSSL is used to generate a 32-byte random number.
    1.openssl rand -out KeyMaterial.bin 32
  • Obtain key material import parameters.
  • Encrypt key materials.
    • First, you must perform Base64 decoding on the public encryption key.
    • Then, use the encryption algorithm (RSAES_OAEP_SHA_1 here) to encrypt the key material.
    • Finally, perform Base64 encoding on the encrypted key material and save it as a text file.
      openssl rand -out KeyMaterial.bin 32
      openssl enc -d -base64 -A -in PublicKey_base64.txt -out PublicKey.bin
      openssl rsautl -encrypt -in KeyMaterial.bin -oaep -inkey PublicKey.bin  -keyform DER  -pubin -out EncryptedKeyMaterial.bin
      openssl enc -e -base64 -A -in EncryptedKeyMaterial.bin -out EncryptedKeyMaterial_base64.txt
  • Upload the encrypted key material and import token.

Use JAVA SDK to encrypt and upload the key material

//Use the latest KMS JAVA SDK
//KmsClient.java

import com.aliyuncs.kms.model.v20160120.*;
import com.aliyuncs.profile.DefaultProfile;

//KMS API encapsulation
public class KmsClient {
        DefaultAcsClient client;

        public KmsClient( String region_id, String ak, String secret) {
                DefaultProfile profile = DefaultProfile.getProfile(region_id, ak, secret);
                this.client = new DefaultAcsClient(profile);
        }

        public CreateKeyResponse createKey() throws Exception {
                CreateKeyRequest request = new CreateKeyRequest();
                request.setOrigin("EXTERNAL"); //Create an external key
                return this.client.getAcsResponse(request);
        }
        //... Omitted. The remaining operations are the same as those in the API method.
}
//example.java
import com.aliyuncs.kms.model.v20160120.*;
import KmsClient
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.MGF1ParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource.PSpecified;
import java.security.spec.X509EncodedKeySpec;
import java.util.Random;
import javax.xml.bind.DatatypeConverter;

public class CreateAndImportExample {
        public static void main(String[] args) {
                String regionId = "cn-hangzhou";
        String accessKeyId = "*** Provide your AccessKeyId ***";
        String accessKeySecret = "*** Provide your AccessKeySecret ***";
        KmsClient kmsclient = new KmsClient(regionId,accessKeyId,accessKeySecret);
        //Create External Key
        try {
                CreateKeyResponse keyResponse = kmsclient.createKey();
                String keyId = keyResponse.KeyMetadata.getKeyId();
                //Generate a 32-bit random number
                byte[] keyMaterial = new byte[32];
                new Random().nextBytes(keyMaterial);
                //Obtain key material import parameters
                GetParametersForImportResponse paramResponse = kmsclient.getParametersForImport(keyId,"RSAES_OAEP_SHA_256");
                String importToekn = paramResponse.getImportToken();
                String encryptPublicKey = paramResponse.getPublicKey();
                //Perform Base64 decoding on the public encryption key
                byte[] publicKeyDer = DatatypeConverter.parseBase64Binary(encryptPublicKey);
                //Parse the RSA public key
                KeyFactory keyFact = KeyFactory.getInstance("RSA");
                X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyDer);
                PublicKey publicKey = keyFact.generatePublic(spec);
                //Encrypt the key material
                Cipher oaepFromAlgo = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
                String hashFunc = "SHA-256";
                OAEPParameterSpec oaepParams = new OAEPParameterSpec(hashFunc, "MGF1", new MGF1ParameterSpec(hashFunc), PSpecified.DEFAULT);
                oaepFromAlgo.init(Cipher.ENCRYPT_MODE, publicKey, oaepParams);
                byte[] cipherDer = oaepFromAlgo.doFinal(keyMaterial);
                //You must perform Base64 encoding on the encrypted key material
                String encryptedKeyMaterial = DatatypeConverter.printBase64Binary(cipherDer);
                //Import the key material
                Long expireTimestamp = 1546272000L; //Unix timestamp, precise to the second, 0 indicates no expiration
                        kmsClient.importKeyMaterial(keyId,encryptedKeyMaterial, expireTimestamp);
        } catch(Exception e) {
                //... Omitted
        }
        }
}