All Products
Document Center

Key Management Service:Import key material into an asymmetric key

Last Updated:Oct 08, 2023

When you create an asymmetric key that has an external key material origin, Key Management Service (KMS) does not generate key material. In this case, you must import your own key material. This topic describes how to import key material into an asymmetric key.

Background information

Keys are basic resources in KMS. A key consists of the key ID, metadata such as the key status, and key material. To create a key, you can use the key material that is generated by KMS or use external key material. If you use external key material to create a key, you must import the key material into the key.

The following table describes whether different types of keys support external key material. For more information about key types, see Key types and specifications.

  • Tick: supports imported key material.

  • Cross: does not support imported key material.

Key type

Import external key material into a symmetric key

Import external key material into an asymmetric key

Default key

  • Customer master key (CMK): 对

  • Service key: 错

  • CMK: 错

  • Service key: 错

Software-protected key


Hardware-protected key



The first time you import key material into a key, the key is associated with the key material. You cannot import different key material into the key.


If the key material of a key is expired or deleted, you can reimport the same key material into the key to reuse the key. You must store the key material in a secure location.


A KMS instance of the hardware key management type is purchased and enabled. For more information, see Purchase and enable a KMS instance.

Import key material in the KMS console

Step 1: Create an asymmetric key

Before you import key material, create an asymmetric key that has an external key material origin.

  1. Log on to the KMS console. In the top navigation bar, select the required region. In the left-side navigation pane, click Keys.

  2. On the Keys tab, select the ID of a KMS instance of the hardware key management type from the Instance ID drop-down list and click Create Key.

  3. In the Create Key panel, configure the parameters and click OK.



    Key Type

    The type of the key. Select Asymmetric Key.

    Key Specifications

    The specification of the key.

      • Symmetric key specifications: Aliyun_AES_256, Aliyun_AES_192, and Aliyun_AES_128

      • Asymmetric key specifications: RSA_2048, RSA_3072, RSA_4096, EC_P256, and EC_P256K

    Key Purpose

    The usage of the key. Valid values:

    • Encrypt/Decrypt: encrypts or decrypts data.

    • Sign/Verify: signs data or verifies a digital signature.

    Key Alias

    The alias of the key. The alias can contain letters, digits, underscores (_), hyphens (-), and forward slashes (/).


    The tag that you want to add to the key. You can use tags to classify and manage keys. A tag consists of a key-value pair.

    • A tag key or a tag value can be up to 128 characters in length and can contain letters, digits, forward slashes (/), backslashes (\), underscores (_), hyphens (-), periods (.), plus signs (+), equal sign (=), colons (:), and at signs (@).

    • A tag key cannot start with aliyun or acs:.

    • You can configure up to 20 key-value pairs for each key.


    The description of the key.

    Advanced Settings

    • The key material origin. Select External.


      Read and select I understand the implications of using the external key materials.

    • Secondary Purpose: Specify a value based on your business requirements.

Step 2: Download a public key and an import token

To import key material into a key, you must obtain a public key and an import token. The public key is used to encrypt key material. The import token allows you to import key material.

  1. Find the key into which you want to import key material and click Details in the Actions column. On the Key Material tab, click Obtain Parameters for Import.

  2. In the Obtain Parameters to Import Key Material dialog box, configure Public Key Type and Encryption Algorithm, and then click Next.

    Set Public Key Type to RSA_2048 and Encryption Algorithm to RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD.

  3. Download a public key and an import token and store them in a secure location.

    • Public Key Format

      • If you select DER Format, the name of the public key file is in the publickey_key-******.bin format.

      • If you select PEM Format, the name of the public key file is in the publickey_key-******.pem format.

    • Import Token: The name of the import token file is in the token_key-******.txt format.


      The import token is valid for 24 hours and can be repeatedly used within this period. After 24 hours, you must download a new import token and a new public key.

Step 3: Encrypt key material

You must generate and encrypt key material in your system environment. The following table describes the keys that are involved during the process.





Target asymmetric key (TAK)

The TAK that you want to import as key material.

Your system environment or tool such as an on-premises key management infrastructure (KMI) or a hardware security module (HSM).

  • TAKpub: the public key of the TAK

  • TAKpriv: the private key of the TAK

Import wrapping key (IWK)

The key that is used to import the TAK.


  • IWKpub: the public key of the IWK


    IWKpub is the public key that you downloaded in the KMS console.

  • IWKpriv: the private key of the IWK

Ephemeral symmetric key (ESK)

The temporary key that is used to encrypt the private key of the TAK.

Your system environment or tool. After you export the TAK, you must immediately destroy the ESK.


  1. Create a private key for your TAK. The specification of the private key must be the same as the specification of the asymmetric key that you created. If you already have the private key for the TAK, skip this step.


    Perform the following operations to make sure that the TAKpriv format meets the requirements: Encode a Rivest-Shamir-Adleman (RSA) private key based on RFC 3447 or an elliptic-curve cryptography (ECC) private key based on RFC 5915. Then, convert the RSA or ECC private key to the Public-Key Cryptography Standards (PKCS) #8 format based on RFC 5208.

  2. Create an ESK.

  3. Use the public key of the IWK to encrypt the ESK. The generated ciphertext is recorded as Cipher(ESK).

  4. Use the ESK to encrypt the private key of the TAK. The generated ciphertext is recorded as Cipher(TAKpriv).

  5. Assemble the encryption results in the Cipher(ESK) || Cipher(TAKpriv) format to obtain encrypted key material.

Example: Use OpenSSL to generate key material in which the RSA_2048 algorithm is used

  1. Create an RSA_2048 private key for your TAK and convert the private key to the PKCS #8 format.

    openssl genrsa -out TakPrivPkcs1.pem 2048
    openssl pkcs8 -topk8 -inform PEM -in TakPrivPkcs1.pem -outform der -nocrypt -out TakPrivPkcs8.bin
  2. Create an AES_256 ESK.

    openssl rand -out EskAes256.bin 32
  3. Use the public key of the IWK to encrypt the ESK and obtain Cipher(ESK). RSA Encryption Scheme - Optimal Asymmetric Encryption Padding (RSAES-OAEP) is used for the encryption. SHA-256 is used as the mask generation function 1 (MGF1) and the hash algorithm.

    openssl pkeyutl -encrypt -pubin -inkey PublicKey.pem  -in EskAes256.bin  -pkeyopt 
    rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 -out 

    Replace PublicKey.pem with the name of the public key file that you downloaded in the KMS console.

  4. Use the ESK to encrypt the private key of the TAK and obtain Cipher(TAKpriv). In the encryption process, the electronic code book (ECB) encryption mode and the PKCS #7 padding mode are used.

    xxd -l 32  -c 32 -ps EskAes256.bin | xargs -I {} openssl enc  -aes-256-ecb -e  -K {} -in 
    TakPrivPkcs8.bin -nosalt -out CipherTakPriv.bin
  5. Assemble the encryption results in the Cipher(ESK) || Cipher(TAKpriv) format and encode the assembled data in Base64.

    cat CipherEsk.bin CipherTakPriv.bin > EncryptedKeyMaterial.bin
    openssl enc -e -base64 -A -in EncryptedKeyMaterial.bin -out EncryptedKeyMaterial_base64.txt

    In the sample code, the EncryptedKeyMaterial_base64.txt file contains the key material.

Step 4: Import key material

On the key details page, click Import Key Material. In the Import Wrapped Key Material dialog box, configure the parameters and click OK.



Wrapped Key Material

Upload the key material file that is generated in Step 3: Encrypt key material.

Import Token

Upload the import token file that is downloaded in Step 2: Download a public key and an import token.

After the key material is imported, the status of the key changes from Pending Import to Enabling.

Import key material by using KMS SDK

You can use KMS SDK for Java to create an RSA or ECC key and import key material into the key. Sample Java code:


The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using the AccessKey pair to perform operations is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. We recommend that you do not save the AccessKey ID or AccessKey secret in your project code. Otherwise, the AccessKey pair may be leaked, and the security of all resources that belong to your account may be compromised.

In this example, the AccessKey pair is saved in the ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variables to implement identity authentication. For more information about how to configure authentication information, see Credentials.

import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource.PSpecified;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import com.aliyuncs.AcsRequest;
import com.aliyuncs.AcsResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.kms.model.v20160120.CreateKeyRequest;
import com.aliyuncs.kms.model.v20160120.CreateKeyResponse;
import com.aliyuncs.kms.model.v20160120.GetParametersForImportRequest;
import com.aliyuncs.kms.model.v20160120.GetParametersForImportResponse;
import com.aliyuncs.kms.model.v20160120.ImportKeyMaterialRequest;
import com.aliyuncs.kms.model.v20160120.ImportKeyMaterialResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.apache.commons.lang3.tuple.Pair;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class BringYourOwnAsymmetricKeySample {
    static String regionId = "cn-hangzhou";
    static String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
    static String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    static String dedicatedKmsInstanceId = "*** Provide your DedicatedKmsInstanceId ***";
    DefaultAcsClient kmsClient;
    private final String SM2PKE_SM4_ECB = "SM2PKE_SM4_ECB";
    private final String RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD = "RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD";
    private static Provider BC = new BouncyCastleProvider();
    private static X9ECParameters x9ECParameters = GMNamedCurves.getByName("sm2p256v1");
    private static ECDomainParameters ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
    static { org.bouncycastle.jce.provider.BouncyCastleProvider());

    public static void main(String[] args) {
        // Initialize KMS SDK. 
        DefaultAcsClient client = getClientForPublicEndpoint(regionId, accessKeyId, accessKeySecret);
        BringYourOwnAsymmetricKeySample sample = new BringYourOwnAsymmetricKeySample(client);

        // Create and import an external EC_SM2 key. 
        sample.doByok("EC_SM2", "EC_SM2", sample.SM2PKE_SM4_ECB, "SM4");
        // Create and import an external EC_P256 key. 
        sample.doByok("EC_P256", "RSA_2048", sample.RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD, "AES_256");
        // Create and import an external RSA key. 
        sample.doByok("RSA_2048", "RSA_2048", sample.RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD, "AES_256");

    public static DefaultAcsClient getClientForPublicEndpoint(String regionId, String accessKeyId, String accessKeySecret) {
         * Construct an Aliyun Client:
         * Set RegionId, AccessKeyId and AccessKeySecret
        IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);
        return client;

    public BringYourOwnAsymmetricKeySample(DefaultAcsClient kmsClient) {
        this.kmsClient = kmsClient;

    public void doByok(String targetKeySpec, String wrappingKeySpec, String wrappingAlgorithm, String ephemeralKeySpec) {
        try {
            // Create an external ECC key. 
            CreateKeyResponse.KeyMetadata keyMetadata = this.createExternalKeyInDkms(dedicatedKmsInstanceId, targetKeySpec, "SIGN/VERIFY");
            String keyId = keyMetadata.getKeyId();
            // Obtain the parameters that are used to import key material. 
            GetParametersForImportResponse parametersForImportResponse = this.getParametersForImport(keyId, wrappingKeySpec,
            String importToken = parametersForImportResponse.getImportToken();
            String publicKeyBase64 = parametersForImportResponse.getPublicKey();
            // Create an ESK. 
            byte[] ephemeralSymmetricKeyPlaintext = this.generateEphemeralSymmetricKey(ephemeralKeySpec);
            // Create a TAK. 
            byte[] targetAsymmetricKeyPlaintext = this.generateTargetAsymmetricKey(targetKeySpec);
            // Use the public key of an IWK to encrypt the ESK. 
            byte[] ephemeralSymmetricKeyCipher = this.encryptEphemeralSymmetricKey(publicKeyBase64,
                wrappingAlgorithm, ephemeralSymmetricKeyPlaintext);
            // Use the ESK to encrypt the TAK. 
            byte[] targetAsymmetricKeyCipher = this.encryptTargetAsymmetricKey(ephemeralSymmetricKeyPlaintext, targetAsymmetricKeyPlaintext,
            // Generate key material. 
            byte[] encryptedKeyMaterial = new byte[ephemeralSymmetricKeyCipher.length + targetAsymmetricKeyCipher.length];
            System.arraycopy(ephemeralSymmetricKeyCipher, 0, encryptedKeyMaterial, 0, ephemeralSymmetricKeyCipher.length);
            System.arraycopy(targetAsymmetricKeyCipher, 0, encryptedKeyMaterial, ephemeralSymmetricKeyCipher.length, targetAsymmetricKeyCipher.length);
            String encryptedKeyMaterialBase64 =  DatatypeConverter.printBase64Binary(encryptedKeyMaterial);
            // Import the key material. 
            this.importKeyMaterial(keyId, encryptedKeyMaterialBase64, importToken, 0L);
        } catch (Exception e) {

    private GetParametersForImportResponse getParametersForImport(String keyId, String keySpec, String algorithm) throws Exception {
        GetParametersForImportRequest request = new GetParametersForImportRequest();
        GetParametersForImportResponse resp;
        try {
            resp = this.getAcsResponseWithRetry(request);
        } catch (Exception e) {
            throw e;
        return resp;

    private CreateKeyResponse.KeyMetadata createExternalKeyInDkms(String dedicatedKmsInstance, String keySpec, String keyUsage) throws Exception {
        CreateKeyRequest request = new CreateKeyRequest();
        // Create an external key.   

        CreateKeyResponse.KeyMetadata ret = null;
        String requestId = null;
        try {
            CreateKeyResponse response = getAcsResponseWithRetry(request);
            ret = response.getKeyMetadata();
            requestId = response.getRequestId();
        } catch (Exception e) {
            throw e;
        return Pair.of(ret, requestId).getKey();

    private <T extends AcsResponse> T getAcsResponseWithRetry(AcsRequest<T> request) throws ServerException,
        ClientException {
        String expStr = "Retry Max Times";
        for (int i = 0; i < 3; i++) {
            try {
                T resp = this.kmsClient.getAcsResponse(request);
                if (resp == null) {
                    throw new ClientException("Get a null response");
                return resp;
            } catch (ServerException e) {
                throw e;
            } catch (ClientException e) {
                expStr = e.toString();
              //need retry
                if (expStr.contains("SDK.ServerUnreachable")) {
                throw e;
        throw new ClientException(expStr);

    private byte[] generateEphemeralSymmetricKey(String ephemeralSymmetricKeySpec) throws Exception {
       // If the ESK is of the AES_256 type, set the length to 32 bits.   
       int ephemeralSymmetricKeyLength = 32; 
        if ("SM4".equals(ephemeralSymmetricKeySpec)) {
            ephemeralSymmetricKeyLength = 16;
        byte[] key = new byte[32];
        new Random().nextBytes(key);

        return key;

    private byte[] generateTargetAsymmetricKey(String keySpec) throws Exception {
        PrivateKey privateKey = null;
        // Create an SM2 key and obtain the value of the D parameter for the private key. 
        if ("EC_SM2".equals(keySpec)) {
            ECPrivateKey ecPrivateKey = (ECPrivateKey)generateSm2KeyPair().getPrivate();
            byte[] dT = ecPrivateKey.getS().toByteArray();
            byte[] d = new  byte[32];
            if (dT.length == 33) {
                System.arraycopy(dT, 1, d, 0, 32);
            return dT.length == 32 ? dT : d;

        // Generate an RSA or ECC private key. 
        if (keySpec.contains("RSA")) {
            String[] keySpecAttrs = keySpec.split("_");
            int bits = Integer.parseInt(keySpecAttrs[keySpecAttrs.length - 1]);
            privateKey = generateRsaKeyPair(bits).getPrivate();
        } else if  (keySpec.contains("EC")) {
            if (keySpec.contains("P256K")) {
                // Generate an EC_P256K private key. 
                privateKey  = generateEccKeyPair("secp256k1").getPrivate();
            } else {
                // Generate an EC_P256 private key. 
                privateKey=   generateEccKeyPair("secp256r1").getPrivate();
        if (privateKey != null) {
            // Return the private key in the PKCS #8 format. 
            return  privateKey.getEncoded();
        return null;

    private  KeyPair generateEccKeyPair(String keySpec)
        throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        ECGenParameterSpec ecSpec = new ECGenParameterSpec(keySpec);
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
        keyPairGenerator.initialize(ecSpec, new SecureRandom());
        return keyPairGenerator.generateKeyPair();
    private  KeyPair generateRsaKeyPair(int length) throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        return keyGen.genKeyPair();

    private KeyPair generateSm2KeyPair() throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", "BC");
        keyGen.initialize(new ECGenParameterSpec("sm2p256v1"), new SecureRandom());
        return keyGen.genKeyPair();

    private byte[] encryptEphemeralSymmetricKey (String publicKeyBase64, String wrappingAlgorithm, byte[] ephemeralSymmetricKeyPlaintext) throws Exception {
        PublicKey publickey = null;
        byte[] enchbk = null;
        if ("RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD".equals(wrappingAlgorithm)) {
            publickey = parseDerPublicKey("RSA", publicKeyBase64);
            Cipher oaepFromAlgo = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSpecified.DEFAULT);
            oaepFromAlgo.init(Cipher.ENCRYPT_MODE, publickey, oaepParams);
            enchbk = oaepFromAlgo.doFinal(ephemeralSymmetricKeyPlaintext);
        } else if ("SM2PKE_SM4_ECB".equals(wrappingAlgorithm)) {
            publickey = parseDerPublicKey("EC", publicKeyBase64, BC);
            BCECPublicKey localECPublicKey = (BCECPublicKey) publickey;
            ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(localECPublicKey.getQ(), ecDomainParameters);
            SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
            sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters));
            enchbk = sm2Engine.processBlock(ephemeralSymmetricKeyPlaintext, 0, ephemeralSymmetricKeyPlaintext.length);

        } else {
            throw new Exception("Invalid wrappingAlgorithm");
        return enchbk;

    private PublicKey parseDerPublicKey(String keyType, String pemKey) throws Exception {
        byte[] derKey = DatatypeConverter.parseBase64Binary(pemKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey);
        return KeyFactory.getInstance(keyType).generatePublic(keySpec);
    private PublicKey parseDerPublicKey(String keyType, String pemKey, Provider provider) throws Exception {
        byte[] derKey = DatatypeConverter.parseBase64Binary(pemKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey);
        return KeyFactory.getInstance(keyType, provider).generatePublic(keySpec);

    private byte[] encryptTargetAsymmetricKey (byte[] secretKey, byte[] targetAsymmetricKeyPlaintext, String wrappingAlgorithm)
        throws Exception {
        if ("RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD".equals(wrappingAlgorithm)) {
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            return cipher.doFinal(targetAsymmetricKeyPlaintext);
        } else if ("SM2PKE_SM4_ECB".equals(wrappingAlgorithm)) {
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "SM4");
            Cipher cipher = Cipher.getInstance("SM4/ECB/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            return cipher.doFinal(targetAsymmetricKeyPlaintext);

        throw new Exception("Invalid WrappingAlgorithm");

    private boolean importKeyMaterial(
        String keyId,
        String material,
        String token,
        Long expire
    ) throws Exception {
        ImportKeyMaterialRequest req = newImportKeyMaterialRequest(
            keyId, material, token, expire);
        try {
            ImportKeyMaterialResponse resp = this.getAcsResponseWithRetry(req);
        } catch (Exception e) {
            throw e;
        return true;

    private ImportKeyMaterialRequest newImportKeyMaterialRequest(
        String keyId,
        String material,
        String token,
        Long expire
    ) {
        ImportKeyMaterialRequest request = new ImportKeyMaterialRequest();
        return request;


Can I delete key material?

Key material is imported into a hardware security module (HSM) cluster. You cannot directly delete key material. You can delete key material by scheduling deletion of the key that uses the key material.


After a key is deleted, the key cannot be restored. Data that is encrypted and data keys that are generated by using the key cannot be decrypted. After you confirm that the key is no longer required, we recommend that you disable the key and schedule the deletion of the key. For more information, see Disable a key.

For more information about how to schedule the deletion of a key, see Manage a key or ScheduleKeyDeletion.

How do I check the key material origin of a key?

  • Method 1: Use the KMS console

    On the Keys page, click the Keys tab, select the ID of the required KMS instance from the Instance ID drop-down list, find the key that you want to manage, and then click Details in the Actions column. On the details page, view the value of Key Material Source.

  • Method 2: Call the DescribeKey operation.

    If the value of Origin is EXTERNAL, the key material is imported. If the value of Origin is Aliyun_KMS, the key material is generated by KMS.

How do I rotate keys that use external key material?

KMS does not support automatic rotation for keys that use external key material. If you want to rotate a key that uses external key material, you must create a different key and import different key material into the key.