All Products
Search
Document Center

Key Management Service:Import key material into an asymmetric key

更新時間:Sep 04, 2024

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.

Important

If your KMS instance of the hardware key management or software key management type does not allow you to import key material or an error is returned when you import key material, contact technical support.

Features

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. This feature is commonly known as the bring your own key (BYOK) feature.

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

  • 对: supports external key material.

  • 错: does not support external 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

×

Usage notes

  • 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.

  • You can import the same key material into a key multiple times based on your business requirements.

  • If the key material of a key expires or is deleted, you can reimport the same key material for the key, This way, you can reuse the key. After you import key material, you cannot export the key material. We recommend that you store the key material in a secure location.

Prerequisites

A KMS instance 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.

Software-protected key

  1. Log on to the KMS console. In the top navigation bar, select a region. In the left-side navigation pane, choose Resource > Keys.

  2. On the Keys tab, select a KMS instance of the software 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.

    Parameter

    Description

    Key Type

    The type of the key. Select Asymmetric Key.

    Key Specifications

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

    Key Usage

    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 (/).

    Tag

    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.

    Note
    • 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 (:), at signs (@), and spaces.

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

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

    Description

    The description of the key.

    Advanced Settings

    • Policy Settings: For more information, see Overview.

    • Key Material Source: Select External (Import Key Material).

      Note

      If you select External (Import Key Material), you must read and select I understand the implications of using the external key materials.

Hardware-protected key

  1. Log on to the KMS console. In the top navigation bar, select a region. In the left-side navigation pane, choose Resource > 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.

    Parameter

    Description

    Key Type

    The type of the key. Select Asymmetric Key.

    Key Specifications

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

    Key Usage

    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 (/).

    Tag

    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.

    Note
    • 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 (:), at signs (@), and spaces.

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

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

    Description

    The description of the key.

    Advanced Settings

    • Policy Settings: For more information, see Overview.

    • Key Material Source: Select External (Import Key Material).

      Note

      If you select External (Import Key Material), you must read and select I understand the implications of using the external key materials.

Step 2: Download a wrapping public key and an import token

To import key material into a key, you must obtain a wrapping public key and an import token. The wrapping 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 click Next.

    Key type

    Key specification

    Wrapping public key type

    Encryption algorithm

    Software-protected key

    • RSA_2048

    • RSA_3072

    • EC_P256

    • EC_P256K

    RSA_2048

    RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD

    Hardware-protected key

    • RSA_2048

    • RSA_3072

    • RSA_4096

    • EC_P256

    • EC_P256K

    RSA_2048

    RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD

  3. Download a wrapping 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_******.bin format.

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

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

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

      • You must use the wrapping public key together with the import token. You cannot mix a wrapping public key and an import token from different downloads.

Step 3: Use the wrapping public key to 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.

Key

Purpose

Provider

Description

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.

KMS.

  • IWKpub: the public key of the IWK

    Note

    IWKpub is the wrapping 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.

N/A

  1. Create a private key for the 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 a private key for the TAK, skip this step.

    Note

    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 into 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 for 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 \
    CipherEsk.bin
    Note

    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
    Note

    In the preceding 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.

Parameter

Description

Wrapped Key Material

Upload the key material file that is generated in Step 3: Use the wrapping public key to encrypt key material.

Import Token

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

Key Material Expired On

You can select Never Expire or specify an expiration time.

Important

If you specify an expiration time for key material, KMS deletes the key material when the expiration time is reached, and you can no longer use the key material. If you want to reuse the key material, you can reimport the same key material into the key.

After you import the key material, the status of the key changes from Pending Import to Enabling.

Import key material by using Alibaba Cloud SDK

You can use Alibaba Cloud SDK to create an RSA or ECC key in KMS and import key material. Sample Java code:

Note

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 and AccessKey Secret in your project code. Otherwise, the AccessKey pair may be leaked and the security of all the resources that belong to your account may be compromised.

In this example, the AccessKey pair is saved in ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variables to implement identity authentication.

import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.ECPrivateKey;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.X509EncodedKeySpec;
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.gm.GMNamedCurves;
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.jcajce.provider.asymmetric.ec.BCECPublicKey;
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 {
        java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    public static void main(String[] args) {
        // Initialize Alibaba Cloud 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,
                wrappingAlgorithm);
            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,
                wrappingAlgorithm);
            // 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) {
            e.printStackTrace();
        }
    }

    private GetParametersForImportResponse getParametersForImport(String keyId, String keySpec, String algorithm) throws Exception {
        GetParametersForImportRequest request = new GetParametersForImportRequest();
        request.setAcceptFormat(FormatType.JSON);
        request.setMethod(MethodType.POST);
        request.setProtocol(ProtocolType.HTTPS);
        request.setKeyId(keyId);
        request.setWrappingKeySpec(keySpec);
        request.setWrappingAlgorithm(algorithm);
        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.   
        request.setOrigin("EXTERNAL"); 
        request.setKeyStoreId(dedicatedKmsInstance);
        request.setKeySpec(keySpec);
        request.setKeyUsage(keyUsage);

        request.setProtocol(ProtocolType.HTTPS);
        request.setAcceptFormat(FormatType.JSON);
        request.setMethod(MethodType.POST);
        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")) {
                    continue;
                }
                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");
        keyGen.initialize(length);
        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();
        request.setAcceptFormat(FormatType.JSON);
        request.setMethod(MethodType.POST);
        request.setProtocol(ProtocolType.HTTPS);
        request.setEncryptedKeyMaterial(material);
        request.setImportToken(token);
        request.setKeyId(keyId);
        request.setKeyMaterialExpireUnix(expire);
        return request;
    }
}
            

FAQ

Can I delete key material?

Yes, you can delete key material.

Important

After imported key material expires or is deleted, the key that uses the key material becomes unavailable until you reimport the same key material.

  • Directly delete key material

    • KMS console: On the details page of the key, click Delete Key Material on the Key Material tab.

    • KMS API: Call the DeleteKeyMaterial operation to delete key material. This operation does not delete your key.

  • KMS deletes key material

    Specify an expiration time for key material when you import the key material. KMS deletes the key material when the expiration time is reached.

How do I reimport the same key material?

After key material of a key expires or is deleted, you can reimport the same key material to continue using the key.

  1. Delete the expired key material.

    On the key details page, click the Key Material tab and then click Delete Key Material.

  2. Re-download a wrapping public key and an import token. For more information, see Step 2: Download a wrapping public key and an import token.

    Note

    The key wrapping process does not affect the content of key material. You can use a different wrapping public key and a different wrapping algorithm to reimport the same key material.

  3. Use the wrapping public key to encrypt the key material. For more information, see Step 3: Use the wrapping public key to encrypt key material.

    Note

    The key material must be the same as the expired key material.

  4. Import the encrypted key material by using the import token. For more information, see Step 4: Import key material.

How do I view 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 KMS instance that you want to manage from the Instance ID drop-down list, find the key whose key material origin you want to view, 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, KMS generated the key material.

How do I rotate a key that uses external key material?

KMS does not support automatic rotation for a key that uses 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.

References