すべてのプロダクト
Search
ドキュメントセンター

Key Management Service:非対称キーへのキーマテリアルのインポート

最終更新日:Apr 01, 2026

外部キーマテリアル起源で非対称キーを作成すると、Key Management Service (KMS) はそのキーに対してキーマテリアルを生成しません。代わりに、ご自身で秘密鍵のキーマテリアルを用意し、それをキーにインポートする必要があります。この手法は一般的に「Bring Your Own Key (BYOK)」と呼ばれます。

重要

ハードウェアキー管理タイプまたはソフトウェアキー管理タイプの KMS インスタンスでキーマテリアルのインポートが許可されていない場合、またはインポート時にエラーが発生した場合は、テクニカルサポートまでお問い合わせください。

サポートされるキー管理タイプ

すべてのキー管理タイプが非対称キーマテリアルのインポートをサポートしているわけではありません。以下の表にサポート状況を示します。

キー管理タイプ対称キーマテリアルのインポート非対称キーマテリアルのインポート
デフォルトキー – カスタマーマスターキーサポート対象非サポート
デフォルトキー – サービスキー非サポート非サポート
ソフトウェア保護キーサポート対象サポート対象
ハードウェア保護キーサポート対象非サポート

キー管理タイプの詳細については、「キー管理タイプおよびキー仕様」をご参照ください。

注意事項

  • 初回インポートは恒久的です。 キーへのキーマテリアルの初回インポート後、そのキーは当該キーマテリアルと恒久的に関連付けられます。その後、同一のキーに異なるキーマテリアルをインポートすることはできません。

  • 再インポートは可能です。 同一のキーマテリアルを複数回キーにインポートできます。キーマテリアルが有効期限切れになったり削除されたりした場合、同じキーマテリアルを再インポートしてキーを再利用してください。

  • キーマテリアルはエクスポートできません。 インポート後、キーマテリアルは KMS から取得できません。インポート前に、安全な場所に保管してください。

前提条件

開始する前に、以下の条件を満たしていることを確認してください。

KMS コンソールでのキーマテリアルのインポート

コンソールベースのインポート手順は、以下の 4 ステップで構成されます。

  1. 外部キーマテリアル起源の非対称キーを作成します。

  2. ラッピング公開鍵およびインポートトークンをダウンロードします。

  3. ラッピング公開鍵を使用して秘密鍵を暗号化します。

  4. 暗号化されたキーマテリアルおよびインポートトークンをアップロードします。

ステップ 1:非対称キーの作成

外部キーマテリアル起源を使用する非対称キーを作成します。手順は、ご利用の KMS インスタンスタイプによって若干異なります。

ソフトウェア保護キー

  1. KMS コンソールにログインします。上部ナビゲーションバーでリージョンを選択し、左側ナビゲーションウィンドウで リソース > キー を選択します。

  2. カスタマーマスターキー タブで、インスタンス ID のドロップダウンリストからソフトウェアキー管理インスタンスを選択し、キーの作成 をクリックします。

  3. キーの作成 パネルで、以下のパラメーターを設定し、OK をクリックします。

    パラメーター説明
    キーの種類非対称キー を選択します。
    キー仕様RSA_2048、RSA_3072、EC_P256、または EC_P256K のいずれかを指定します。
    キー使用目的ENCRYPT/DECRYPT:データの暗号化または復号。SIGN/VERIFY:データの署名またはデジタル署名の検証。
    キーのエイリアスキーの別名です。使用可能な文字:英字、数字、アンダースコア (_)、ハイフン (-)、およびスラッシュ (/)。
    タグキータグ値キーの分類および管理に使用するタグです。タグキーおよびタグ値は最大 128 文字(英字、数字、/\_-.+=:@、空白)まで使用可能です。タグキーは aliyun または acs: で始めてはいけません。1 つのキーにつき最大 20 個のタグキーと値のペアを設定できます。
    説明キーの任意の説明文です。
    ポリシー設定詳細設定 内)概要「」をご参照ください。
    キーマテリアルの起源詳細設定 内)外部(キーマテリアルのインポート) を選択します。「外部キーマテリアルを使用することによる影響について理解しました」という確認事項を読み、チェックを入れてください。

ハードウェア保護キー

  1. KMS コンソールにログインします。上部ナビゲーションバーでリージョンを選択し、左側ナビゲーションウィンドウで リソース > キー を選択します。

  2. カスタマーマスターキー タブで、インスタンス ID のドロップダウンリストからハードウェアキー管理インスタンスを選択し、キーの作成 をクリックします。

  3. キーの作成 パネルで、以下のパラメーターを設定し、OK をクリックします。

    パラメーター説明
    キーの種類非対称キー を選択します。
    キー仕様RSA_2048、RSA_3072、RSA_4096、EC_P256、または EC_P256K のいずれかを指定します。
    キーの使用目的ENCRYPT/DECRYPT:データの暗号化または復号。SIGN/VERIFY:データの署名またはデジタル署名の検証。
    キーのエイリアスキーの別名です。使用可能な文字:英字、数字、アンダースコア (_)、ハイフン (-)、およびスラッシュ (/)。
    タグキータグ値キーの分類および管理に使用するタグです。タグキーおよびタグ値は最大 128 文字(英字、数字、/\_-.+=:@、空白)まで使用可能です。タグキーは aliyun または acs: で始めてはいけません。1 つのキーにつき最大 20 個のタグキーと値のペアを設定できます。
    説明キーの任意の説明文です。
    ポリシー設定詳細設定 内)概要「」をご参照ください。
    キーマテリアルの起源詳細設定 内)外部(キーマテリアルのインポート) を選択します。「外部キーマテリアルを使用することによる影響について理解しました」という確認事項を読み、チェックを入れてください。

ステップ 2:ラッピング公開鍵およびインポートトークンのダウンロード

キーマテリアルをインポートするには、KMS から次の 2 つのファイルを取得する必要があります。

  • ラッピング公開鍵 — アップロード前にキーマテリアルを暗号化するために使用します。

  • インポートトークン — インポート操作を承認します。

  1. 作成したキーを見つけ、詳細 をクリックします(操作 列内)。キーマテリアル タブで、インポート用パラメーターの取得 をクリックします。

  2. キーマテリアルのインポート用パラメーターの取得 ダイアログボックスで、公開鍵の種類 および 暗号化アルゴリズム を選択し、次へ をクリックします。以下の表を参考に、キーに適したラッピング公開鍵の種類および暗号化アルゴリズムを選択してください。

    キーマテリアルの種類キー仕様ラッピング公開鍵の種類暗号化アルゴリズム
    RSA 秘密鍵(ソフトウェア保護)RSA_2048、RSA_3072RSA_2048RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD
    ECC 秘密鍵(ソフトウェア保護)EC_P256、EC_P256KRSA_2048RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD
    RSA 秘密鍵(ハードウェア保護)RSA_2048、RSA_3072、RSA_4096RSA_2048RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD
    ECC 秘密鍵(ハードウェア保護)EC_P256、EC_P256KRSA_2048RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD
    • 両方のファイルをダウンロードし、安全な場所に保存してください。

      • DER 形式の公開鍵:ファイル名は publickey_******.bin の形式です。

      • PEM 形式の公開鍵:ファイル名は publickey_******.pem の形式です。

      • インポートトークン:ファイル名は token_******.txt の形式です。

    重要
    • インポートトークンは 24 時間有効であり、その期間内であれば再利用可能です。24 時間経過後は、新しいインポートトークンおよび新しいラッピング公開鍵をダウンロードしてください。

    • 必ず同一のダウンロードから取得したラッピング公開鍵およびインポートトークンを使用してください。異なるダウンロードから取得したファイルを混在させないでください。

    ステップ 3:秘密鍵の暗号化

    アップロード前に秘密鍵を暗号化する必要があります。この暗号化では、3 つの鍵を用いた二重ラッピング方式が採用されます。

    略称種類提供元説明
    対象非対称キーTAKRSA または ECC キーペアお客様のシステム、KMI、または HSM使用するキーペアです。TAKpub は公開鍵、TAKpriv はインポートする秘密鍵です。
    インポートラッピング鍵IWKRSA キーペアKMSインポートを保護するために使用されるキーペアです。IWKpub はダウンロードしたラッピング公開鍵です。
    一時的対称鍵ESKAES-256(または SM4)お客様のシステムTAKpriv を暗号化するための一時的な対称鍵です。使用後は直ちに破棄してください。

    TAKpriv のフォーマット要件:

    秘密鍵をその種類に応じてエンコードします(RSA:RFC 3447、ECC:RFC 5915)、その後 PKCS #8 形式(RFC 5208)に変換します。最終出力は DER エンコーディングである必要があります。

    暗号化手順:

    1. PKCS #8 DER 形式で TAKpriv を準備します。すでにこの形式の秘密鍵をお持ちの場合は、このステップをスキップできます。

    2. AES-256 ESK(32 バイトのランダム値)を生成します。

    3. RSAES-OAEP(ハッシュおよび MGF1 に SHA-256 を使用)を用いて IWKpub で ESK を暗号化します。結果は Cipher(ESK) です。

    4. AES-256 ECB モードおよび PKCS #7 パディングを用いて ESK で TAKpriv を暗号化します。結果は Cipher(TAKpriv) です。

    5. 2 つの暗号文を Cipher(ESK) || Cipher(TAKpriv) の順序で連結し、Base64 エンコーディングします。これがアップロードする暗号化キーマテリアルです。

    例:OpenSSL を使用した RSA_2048 秘密鍵の暗号化

    # ステップ 1:TAK 用の RSA_2048 秘密鍵を生成し、PKCS #8 DER 形式に変換
    openssl genrsa -out TakPrivPkcs1.pem 2048
    openssl pkcs8 -topk8 -inform PEM -in TakPrivPkcs1.pem -outform der -nocrypt -out TakPrivPkcs8.bin
    
    # ステップ 2:AES-256 ESK(32 バイト)を生成
    openssl rand -out EskAes256.bin 32
    
    # ステップ 3:RSAES-OAEP(SHA-256)を用いて IWK 公開鍵で ESK を暗号化
    # PublicKey.pem は、KMS コンソールからダウンロードしたラッピング公開鍵ファイルに置き換えてください。
    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
    
    # ステップ 4:AES-256 ECB + PKCS #7 パディングを用いて ESK で TAKpriv を暗号化
    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:連結および Base64 エンコーディング
    cat CipherEsk.bin CipherTakPriv.bin > EncryptedKeyMaterial.bin
    openssl enc -e -base64 -A -in EncryptedKeyMaterial.bin -out EncryptedKeyMaterial_base64.txt

    EncryptedKeyMaterial_base64.txt ファイルには、次のステップでアップロードする暗号化キーマテリアルが含まれています。

    ステップ 4:キーマテリアルのインポート

    1. キーの詳細ページで、キーマテリアルのインポート をクリックします。

    2. ラップされたキーマテリアルのインポート ダイアログボックスで、以下のパラメーターを設定し、OK をクリックします。

      パラメーター説明
      ラップされたキーマテリアルステップ 3 で生成した暗号化キーマテリアルファイルをアップロードします。
      インポートトークンステップ 2 でダウンロードしたインポートトークンファイルをアップロードします。
      キー材料の有効期限切れ日有効期限なし を選択するか、有効期限を指定します。有効期限を設定した場合、有効期限が過ぎると KMS がキーマテリアルを削除し、キーは同一のキーマテリアルを再インポートするまで利用不可になります。

    インポート後、キーのステータスは インポート待ち から 有効化中 に変わります。

    Alibaba Cloud SDK を使用したキーマテリアルのインポート

    以下の Java の例では、KMS で外部非対称キーを作成し、Alibaba Cloud SDK を使用してキーマテリアルをインポートする方法を示します。RSA または ECC

    認証情報は環境変数から読み込まれます。AccessKey ID および AccessKey Secret は、プロジェクト内にハードコードせず、ALIBABA_CLOUD_ACCESS_KEY_ID および ALIBABA_CLOUD_ACCESS_KEY_SECRET という環境変数に格納してください。

    すべての例では、最終的なキーマテリアルペイロードを構築する前に、一時的対称鍵を暗号化するために RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD または SM2PKE_SM4_ECB アルゴリズムを使用します。

    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) {
            // Alibaba Cloud SDK の初期化
            DefaultAcsClient client = getClientForPublicEndpoint(regionId, accessKeyId, accessKeySecret);
            BringYourOwnAsymmetricKeySample sample = new BringYourOwnAsymmetricKeySample(client);
    
            // 外部 EC_SM2 キーの作成およびインポート
            sample.doByok("EC_SM2", "EC_SM2", sample.SM2PKE_SM4_ECB, "SM4");
            // 外部 EC_P256 キーの作成およびインポート
            sample.doByok("EC_P256", "RSA_2048", sample.RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD, "AES_256");
            // 外部 RSA キーの作成およびインポート
            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) {
            /**
             * Aliyun Client の構築:
             * RegionId、AccessKeyId、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 {
                // 外部 ECC キーの作成
                CreateKeyResponse.KeyMetadata keyMetadata = this.createExternalKeyInDkms(dedicatedKmsInstanceId, targetKeySpec, "SIGN/VERIFY");
                String keyId = keyMetadata.getKeyId();
                // キーマテリアルのインポートに使用するパラメーターの取得
                GetParametersForImportResponse parametersForImportResponse = this.getParametersForImport(keyId, wrappingKeySpec,
                    wrappingAlgorithm);
                String importToken = parametersForImportResponse.getImportToken();
                String publicKeyBase64 = parametersForImportResponse.getPublicKey();
                // ESK の作成
                byte[] ephemeralSymmetricKeyPlaintext = this.generateEphemeralSymmetricKey(ephemeralKeySpec);
                // TAK の作成
                byte[] targetAsymmetricKeyPlaintext = this.generateTargetAsymmetricKey(targetKeySpec);
                // IWK の公開鍵を用いて ESK を暗号化
                byte[] ephemeralSymmetricKeyCipher = this.encryptEphemeralSymmetricKey(publicKeyBase64,
                    wrappingAlgorithm, ephemeralSymmetricKeyPlaintext);
                // ESK を用いて TAK を暗号化
                byte[] targetAsymmetricKeyCipher = this.encryptTargetAsymmetricKey(ephemeralSymmetricKeyPlaintext, targetAsymmetricKeyPlaintext,
                    wrappingAlgorithm);
                // 暗号化キーマテリアルの構築:Cipher(ESK) || Cipher(TAKpriv)
                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);
                // キーマテリアルのインポート
                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();
            // 外部キーの作成
            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 {
           // ESK が AES_256 の場合、長さを 32 バイトに設定
           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;
            // SM2 キーを作成し、秘密鍵の D パラメーター値を取得
            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;
            }
    
            // RSA または ECC 秘密鍵を生成
            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")) {
                    // EC_P256K 秘密鍵を生成
                    privateKey  = generateEccKeyPair("secp256k1").getPrivate();
                } else {
                    // EC_P256 秘密鍵を生成
                    privateKey=   generateEccKeyPair("secp256r1").getPrivate();
                }
            }
            if (privateKey != null) {
                // PKCS #8 形式で秘密鍵を返す
                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;
        }
    }

    以下のプレースホルダーを置き換えてください。

    プレースホルダー説明
    * Provide your DedicatedKmsInstanceId *専用 KMS インスタンスの ID
    cn-hangzhouKMS インスタンスが展開されているリージョン

    よくある質問

    キーマテリアルを削除できますか?

    はい。キーマテリアルが削除または有効期限切れになると、同一のキーマテリアルを再インポートするまでキーは利用不可になります。

    直接キーマテリアルを削除するには、以下の手順を実行します。

    • KMS コンソール:キーの詳細ページで、キーマテリアル タブをクリックし、キーマテリアルの削除 をクリックします。

    • KMS APIDeleteKeyMaterial 操作を呼び出します。これにより、キーマテリアルのみが削除され、キー自体は削除されません。

    自動削除を設定するには、インポート時に有効期限を指定します。KMS は有効期限に達するとキーマテリアルを削除します。

    同一のキーマテリアルを再インポートするにはどうすればよいですか?

    キーマテリアルが有効期限切れまたは削除された場合、同一のキーマテリアルを再インポートしてキーを復元できます。

    1. キーの詳細ページで、キーマテリアル タブをクリックし、キーマテリアルの削除 をクリックして、有効期限切れのキーマテリアルをクリアします。

    2. 新しいラッピング公開鍵およびインポートトークンをダウンロードします(ステップ 2 を参照)。ラッピング手順はキーマテリアルの内容に影響しないため、異なるラッピング公開鍵およびアルゴリズムを使用できます。

    3. 新しいラッピング公開鍵を使用してキーマテリアルを暗号化します(ステップ 3 を参照)。キーマテリアル自体は元のものと同一である必要があります。

    4. 新しいインポートトークンとともに暗号化キーマテリアルをアップロードします(ステップ 4 を参照)。

    キーのキーマテリアルの起源を確認するにはどうすればよいですか?

    • KMS コンソールカスタマーマスターキー タブで、該当のキーを見つけ、詳細 をクリックします(操作 列内)。詳細ページの キーマテリアルの起源 フィールドを確認します。

    • KMS APIDescribeKey を呼び出します。Origin フィールドが EXTERNAL の場合、キーマテリアルはインポートされています。また、Aliyun_KMS の場合、KMS がキーマテリアルを生成しています。

    インポートされたキーマテリアルでキーのローテーションは機能しますか?

    キーのローテーションのサポート状況は、キーの種類によって異なります。

    • インポートされたキーマテリアルを持つソフトウェア保護対称キー:即時手動ローテーションのみがサポートされます。自動定期ローテーションはサポートされていません。詳細については、「Bring-Your-Own-Key (BYOK) キーのローテーション」をご参照ください。

    • インポートされたキーマテリアルを持つソフトウェア保護非対称キー:ローテーションはサポートされていません。

    • インポートされたキーマテリアルを持つハードウェア保護キー(対称および非対称):ローテーションはサポートされていません。

    次のステップ

    参考文献