全部产品
Search
文档中心

Key Management Service:Impor bahan kunci ke dalam kunci asimetris

更新时间:Nov 10, 2025

Saat membuat kunci asimetris dengan sumber bahan kunci eksternal, Key Management Service (KMS) tidak menghasilkan bahan kuncinya. Sebagai gantinya, Anda harus mengimpor bahan kunci milik Anda sendiri. Topik ini menjelaskan cara mengimpor bahan kunci ke dalam kunci asimetris.

Penting

Jika instans manajemen kunci perangkat lunak atau instans manajemen kunci perangkat keras Anda tidak mendukung pengimporan bahan kunci, atau jika terjadi kesalahan saat mengimpor bahan kunci, hubungi dukungan teknis Alibaba Cloud untuk meningkatkan instans tersebut.

Pengantar

Kunci merupakan sumber daya dasar di KMS. Sebuah kunci terdiri dari ID kunci, metadata dasar seperti status kunci, dan bahan kunci. Saat membuat kunci, Anda dapat memilih agar KMS menghasilkan bahan kuncinya atau menggunakan bahan kunci dari sumber eksternal. Jika Anda memilih sumber eksternal, Anda harus mengimpor bahan kunci eksternal tersebut ke dalam kunci. Fitur ini sering disebut Bring Your Own Key (BYOK).

Tabel berikut menjelaskan jenis manajemen kunci KMS yang mendukung pengimporan bahan kunci. Untuk informasi selengkapnya tentang jenis manajemen kunci, lihat Jenis manajemen kunci dan spesifikasi kunci.

  • Check mark: Menunjukkan bahwa pengimporan bahan kunci yang sesuai didukung.

  • Cross mark: Menunjukkan bahwa pengimporan bahan kunci yang sesuai tidak didukung.

Jenis manajemen kunci

Impor bahan kunci simetris

Impor bahan kunci asimetris

Kunci default

  • Kunci utama pelanggan: √

  • Kunci layanan: ×

  • Kunci utama pelanggan: ×

  • Kunci layanan: ×

Kunci yang dilindungi perangkat lunak

Kunci yang dilindungi perangkat keras

×

Catatan penggunaan

  • Saat pertama kali mengimpor bahan kunci ke dalam suatu kunci, kunci tersebut secara permanen dikaitkan dengan bahan kunci tersebut. Anda tidak dapat mengimpor bahan kunci yang berbeda ke dalam kunci tersebut.

  • Anda dapat mengimpor ulang bahan kunci yang sama ke dalam kunci KMS sesuai kebutuhan, tetapi tidak dapat mengimpor bahan kunci yang berbeda.

  • Jika bahan kunci kedaluwarsa atau dihapus, Anda dapat mengimpor ulang bahan kunci yang sama agar kunci tersebut tersedia kembali. Setelah diimpor, bahan kunci tidak dapat diekspor. Simpan bahan kunci Anda di lokasi yang aman.

Prasyarat

Anda telah membeli dan mengaktifkan instans KMS. Untuk informasi selengkapnya, lihat Beli dan aktifkan instans KMS.

Impor bahan kunci di konsol KMS

Langkah 1: Buat kunci asimetris

Sebelum mengimpor bahan kunci, Anda harus membuat kunci asimetris dengan sumber bahan kunci eksternal.

Kunci yang dilindungi perangkat lunak

  1. Masuk ke Konsol KMS. Di bilah navigasi atas, pilih wilayah. Di panel navigasi sebelah kiri, pilih Resource > Keys.

  2. Di tab Customer Master Keys, pilih instans KMS yang dikelola perangkat lunak dari daftar drop-down Instance ID, lalu klik Create Key.

  3. Di panel Create Key, atur item konfigurasi, lalu klik OK.

    Item konfigurasi

    Deskripsi

    Key Type

    Jenis kunci. Pilih Asymmetric Key.

    Key Specifications

    Key Usage

    Tujuan kunci. Nilai yang valid:

    • Encrypt/Decrypt: Enkripsi dan dekripsi data.

    • Sign/Verify: Pembuatan dan verifikasi tanda tangan digital.

    Key Alias

    Alias kunci. Alias dapat berisi huruf, angka, garis bawah (_), tanda hubung (-), dan garis miring (/).

    Tag

    Tag yang akan ditambahkan ke kunci. Gunakan tag untuk mengklasifikasikan dan mengelola kunci. Setiap tag adalah pasangan kunci-nilai yang terdiri dari kunci tag dan nilai tag.

    Catatan
    • Kunci tag atau nilai tag dapat memiliki panjang hingga 128 karakter dan dapat berisi huruf, angka, garis miring (/), garis miring terbalik (\), garis bawah (_), tanda hubung (-), titik (.), tanda tambah (+), tanda sama dengan (=), titik dua (:), tanda @, dan spasi.

    • Kunci tag tidak boleh dimulai dengan aliyun atau acs:.

    • Anda dapat mengonfigurasi hingga 20 pasangan kunci-nilai untuk setiap kunci.

    Description

    Deskripsi kunci.

    Advanced Settings

    • Policy Settings: Untuk informasi selengkapnya, lihat Ikhtisar kebijakan kunci.

    • Key Material Origin: Pilih External (Import Key Material).

      Catatan

      Baca dan pilih Saya memahami implikasi dari penggunaan bahan kunci eksternal.

Kunci yang dilindungi perangkat keras

  1. Masuk ke Konsol KMS. Di bilah navigasi atas, pilih wilayah. Di panel navigasi sebelah kiri, pilih Resource > Keys.

  2. Di tab Customer Master Keys, pilih instans manajemen kunci perangkat keras untuk Instance ID, lalu klik Create Key.

  3. Di panel Create Key, konfigurasi parameter, lalu klik OK.

    Item konfigurasi

    Deskripsi

    Key Type

    Pilih Asymmetric Key.

    Key Specifications

    Key Usage

    Tujuan kunci. Nilai yang valid:

    • Encrypt/Decrypt: Enkripsi dan dekripsi data.

    • Sign/Verify: Pembuatan dan verifikasi tanda tangan digital.

    Key Alias

    Alias kunci. Alias dapat berisi huruf, angka, garis bawah (_), tanda hubung (-), dan garis miring (/).

    Tag

    Tag yang akan ditambahkan ke kunci. Anda dapat menggunakan tag untuk mengklasifikasikan dan mengelola kunci. Setiap tag adalah pasangan kunci-nilai yang terdiri dari kunci tag dan nilai tag.

    Catatan
    • Kunci tag atau nilai tag dapat memiliki panjang hingga 128 karakter dan dapat berisi huruf, angka, garis miring (/), garis miring terbalik (\), garis bawah (_), tanda hubung (-), titik (.), tanda tambah (+), tanda sama dengan (=), titik dua (:), tanda @, dan spasi.

    • Kunci tag tidak boleh dimulai dengan aliyun atau acs:.

    • Anda dapat mengonfigurasi hingga 20 pasangan kunci-nilai untuk setiap kunci.

    Description

    Deskripsi kunci.

    Advanced Settings

    • Policy Settings: Untuk informasi selengkapnya, lihat Ikhtisar kebijakan kunci.

    • Key Material Origin: Pilih External (Import Key Material).

      Catatan

      Baca dan pilih I understand the implications of using external key material.

Langkah 2: Unduh kunci publik pembungkus dan token impor

Parameter untuk mengimpor bahan kunci mencakup kunci publik pembungkus dan token impor. Kunci publik pembungkus digunakan untuk mengenkripsi bahan kunci guna melindunginya selama proses impor, sedangkan token impor diperlukan saat mengimpor bahan kunci.

  1. Temukan kunci target, lalu klik Details di kolom Actions. Di halaman detail kunci, pada bagian Key Material, klik Obtain Parameters for Import.

  2. Di kotak dialog Obtain Parameters to Import Key Material, pilih Public Key Type dan Encryption Algorithm, lalu klik Next.

    Jenis manajemen kunci

    Spesifikasi kunci

    Jenis kunci publik pembungkus

    Algoritma enkripsi

    Kunci yang dilindungi perangkat lunak

    • RSA_2048

    • RSA_3072

    • EC_P256

    • EC_P256K

    RSA_2048

    RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD

    Kunci yang dilindungi perangkat keras

    • RSA_2048

    • RSA_3072

    • RSA_4096

    • EC_P256

    • EC_P256K

    RSA_2048

    RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD

  3. Unduh kunci publik pembungkus dan token impor, lalu simpan di lokasi yang aman.

    • Public Key Format:

      • DER Format: Nama file yang diunduh secara default adalah publickey_******.bin.

      • PEM Format: File yang diunduh secara default bernama publickey_******.pem.

    • Import Token: File yang diunduh secara default bernama token_******.txt.

      Penting
      • Token impor berlaku selama 24 jam dan dapat digunakan beberapa kali dalam periode validitas tersebut. Setelah kedaluwarsa, Anda harus mendapatkan token impor dan kunci publik baru.

      • Kunci publik pembungkus dan token impor harus digunakan bersama-sama. Anda tidak dapat menggunakan kunci publik pembungkus dengan token impor dari unduhan yang berbeda.

Langkah 3: Gunakan kunci publik pembungkus untuk mengenkripsi bahan kunci

Hasilkan dan enkripsi bahan kunci di lingkungan sistem Anda. Tabel berikut menjelaskan kunci-kunci yang digunakan dalam proses tersebut.

Kunci

Tujuan

Penyedia

Deskripsi

Kunci asimetris target (TAK)

Kunci asimetris target untuk diimpor.

Lingkungan sistem atau alat Anda seperti infrastruktur manajemen kunci (KMI) lokal atau modul keamanan perangkat keras (HSM).

  • TAKpub: Kunci publik

  • TAKpriv: Kunci privat

Kunci pembungkus impor (IWK)

Kunci enkripsi yang digunakan untuk mengimpor TAK.

Alibaba Cloud KMS.

  • IWKpub: kunci publik IWK

    Catatan

    IWKpub adalah kunci publik pembungkus yang Anda unduh dari konsol Layanan Manajemen Kunci.

  • IWKpriv: kunci privat IWK

Kunci simetris sementara (ESK)

Kunci simetris sementara yang langsung mengenkripsi TAKpriv.

Hancurkan sistem atau alat di lingkungan sumber segera setelah Anda mengekspor TAK.

N/A

  1. Buat kunci privat asimetris target (TAKpriv). Spesifikasi kunci harus sama dengan yang Anda pilih saat membuat kunci asimetris. Jika Anda sudah memiliki TAKpriv, lewati langkah ini.

    Catatan

    Format TAKpriv harus mematuhi standar berikut: Kunci privat RSA dikodekan berdasarkan RFC 3447. Kunci privat ECC dikodekan berdasarkan RFC 5915. Kemudian, kunci tersebut dibungkus ke dalam format PKCS#8 berdasarkan RFC 5208.

  2. Buat ESK.

  3. Gunakan kunci publik pembungkus impor (IWKpub) untuk mengenkripsi ESK. Ini menghasilkan ciphertext ESK (Cipher(ESK)).

  4. Gunakan ESK untuk mengenkripsi TAKpriv. Ini menghasilkan ciphertext kunci privat asimetris target (Cipher(TAKpriv)).

  5. Rakit hasilnya dalam format Cipher(ESK)||Cipher(TAKpriv) untuk mendapatkan bahan kunci terenkripsi.

Contoh: Gunakan OpenSSL untuk menghasilkan bahan kunci untuk algoritma RSA_2048

  1. Buat kunci privat asimetris target untuk algoritma RSA_2048 dan konversi kunci privat ke format PKCS#8.

    openssl genrsa -out TakPrivPkcs1.pem 2048
    openssl pkcs8 -topk8 -inform PEM -in TakPrivPkcs1.pem -outform der -nocrypt -out TakPrivPkcs8.bin
  2. Buat kunci sementara (ESK) untuk algoritma AES_256.

    openssl rand -out EskAes256.bin 32
  3. Gunakan kunci publik pembungkus impor (IWKpub) untuk mengenkripsi ESK. Ini menghasilkan ciphertext ESK (Cipher(ESK)). Enkripsi dilakukan berdasarkan standar RSAES-OAEP, menggunakan MGF1 dan SHA256 sebagai algoritma hash.

    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
    Catatan

    Ganti PublicKey.pem dengan nama file kunci publik yang Anda unduh dari konsol KMS.

  4. Gunakan ESK untuk mengenkripsi TAKpriv. Ini menghasilkan ciphertext kunci privat asimetris target (Cipher(TAKpriv)). Mode enkripsi adalah ECB dan mode padding adalah PKCS#7 Padding.

    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. Rakit hasilnya dalam format Cipher(ESK) || Cipher(TAKpriv), lalu lakukan encoding Base64.

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

    File EncryptedKeyMaterial_base64.txt adalah file bahan kunci yang akan diimpor ke KMS.

Langkah 4: Impor bahan kunci

Di halaman detail kunci, klik Import Key Material. Di kotak dialog Import Wrapped Key Material yang muncul, konfigurasi parameter, lalu klik OK.

Item konfigurasi

Deskripsi

Wrapped Key Material

Unggah file bahan kunci yang dihasilkan di Langkah 3: Gunakan kunci publik pembungkus untuk mengenkripsi bahan kunci.

Import Token

Unggah file token impor yang diunduh di Langkah 2: Unduh kunci publik pembungkus dan token impor.

Key Material Expired On

Anda dapat memilih Never Expire atau menentukan waktu kedaluwarsa.

Penting

Jika Anda menentukan waktu kedaluwarsa untuk bahan kunci, KMS akan menghapus bahan kunci tersebut saat waktu kedaluwarsa tercapai, dan Anda tidak dapat lagi menggunakan bahan kunci tersebut. Jika ingin menggunakan kembali bahan kunci tersebut, Anda dapat mengimpor ulang bahan kunci yang sama ke dalam kunci.

Setelah bahan kunci diimpor, status kunci berubah dari Pending Import menjadi Enabling.

Impor bahan kunci menggunakan SDK

Anda dapat menggunakan SDK Alibaba Cloud untuk membuat kunci algoritma RSA dan ECC di KMS dan mengimpor bahan kunci. Berikut adalah contoh kode Java:

Catatan

Pasangan AccessKey Akun Alibaba Cloud memiliki izin atas semua operasi API. Menggunakan pasangan AccessKey untuk melakukan operasi merupakan operasi berisiko tinggi. Selain itu, gunakan Pengguna RAM untuk memanggil operasi API atau melakukan O&M rutin. Kami menyarankan agar Anda tidak menyimpan ID AccessKey dan Rahasia AccessKey di kode proyek Anda. Jika Anda melakukannya, pasangan AccessKey mungkin bocor dan keamanan semua sumber daya yang dimiliki akun Anda mungkin terganggu.

Dalam contoh ini, pasangan AccessKey disimpan dalam variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID dan ALIBABA_CLOUD_ACCESS_KEY_SECRET untuk melakukan otentikasi identitas.

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) {
        // Inisialisasi SDK KMS.
        DefaultAcsClient client = getClientForPublicEndpoint(regionId, accessKeyId, accessKeySecret);
        BringYourOwnAsymmetricKeySample sample = new BringYourOwnAsymmetricKeySample(client);

        // Buat dan impor kunci EC_SM2 eksternal.
        sample.doByok("EC_SM2", "EC_SM2", sample.SM2PKE_SM4_ECB, "SM4");
        // Buat dan impor kunci EC_P256 eksternal.
        sample.doByok("EC_P256", "RSA_2048", sample.RSAES_OAEP_SHA_256_AES_256_ECB_PKCS7_PAD, "AES_256");
        // Buat dan impor kunci RSA eksternal.
        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) {
        /**
         * Konstruksi Klien Aliyun:
         * Atur RegionId, AccessKeyId, dan 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 {
            // Buat kunci ECC eksternal.
            CreateKeyResponse.KeyMetadata keyMetadata = this.createExternalKeyInDkms(dedicatedKmsInstanceId, targetKeySpec, "SIGN/VERIFY");
            String keyId = keyMetadata.getKeyId();
            // Dapatkan parameter yang digunakan untuk mengimpor bahan kunci.
            GetParametersForImportResponse parametersForImportResponse = this.getParametersForImport(keyId, wrappingKeySpec,
                wrappingAlgorithm);
            String importToken = parametersForImportResponse.getImportToken();
            String publicKeyBase64 = parametersForImportResponse.getPublicKey();
            // Buat ESK.
            byte[] ephemeralSymmetricKeyPlaintext = this.generateEphemeralSymmetricKey(ephemeralKeySpec);
            // Buat TAK.
            byte[] targetAsymmetricKeyPlaintext = this.generateTargetAsymmetricKey(targetKeySpec);
            // Gunakan kunci publik IWK untuk mengenkripsi ESK.
            byte[] ephemeralSymmetricKeyCipher = this.encryptEphemeralSymmetricKey(publicKeyBase64,
                wrappingAlgorithm, ephemeralSymmetricKeyPlaintext);
            // Gunakan ESK untuk mengenkripsi TAK.
            byte[] targetAsymmetricKeyCipher = this.encryptTargetAsymmetricKey(ephemeralSymmetricKeyPlaintext, targetAsymmetricKeyPlaintext,
                wrappingAlgorithm);
            // Hasilkan bahan kunci.
            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);
            // Impor bahan kunci.
            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();
        // Buat kunci eksternal.
        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();
              //perlu retry
                if (expStr.contains("SDK.ServerUnreachable")) {
                    continue;
                }
                throw e;
            }
        }
        throw new ClientException(expStr);
    }

    private byte[] generateEphemeralSymmetricKey(String ephemeralSymmetricKeySpec) throws Exception {
       // Jika ESK bertipe AES_256, atur panjang menjadi 32 bit.
       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;
        // Buat kunci SM2 dan dapatkan nilai parameter D untuk kunci privat.
        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;
        }

        // Hasilkan kunci privat RSA atau 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")) {
                // Hasilkan kunci privat EC_P256K.
                privateKey  = generateEccKeyPair("secp256k1").getPrivate();
            } else {
                // Hasilkan kunci privat EC_P256.
                privateKey=   generateEccKeyPair("secp256r1").getPrivate();
            }
        }
        if (privateKey != null) {
            // Kembalikan kunci privat dalam format 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;
    }
}
            

FAQ

Apakah saya dapat menghapus bahan kunci?

Ya, Anda bisa.

Penting

Setelah bahan kunci yang diimpor kedaluwarsa atau dihapus, kunci yang menggunakan bahan kunci tersebut menjadi tidak tersedia. Untuk menggunakan kembali kunci tersebut, Anda harus mengimpor ulang bahan kunci yang sama.

  • Hapus bahan kunci secara langsung

    • Di konsol, pada halaman detail kunci, di area Key Material, klik Delete Key Material.

    • Operasi API: Panggil operasi DeleteKeyMaterial untuk menghapus bahan kunci. Operasi ini tidak menghapus kunci Anda.

  • Biarkan KMS menghapus bahan kunci setelah kedaluwarsa

    Saat mengimpor bahan kunci, Anda dapat mengatur waktu kedaluwarsa. KMS akan menghapus bahan kunci setelah waktu yang ditentukan.

Bagaimana cara mengimpor ulang bahan kunci yang sama?

Setelah bahan kunci kedaluwarsa atau dihapus, Anda dapat mengimpor ulang bahan kunci yang sama untuk terus menggunakan kunci tersebut.

  1. Hapus bahan kunci yang kedaluwarsa.

    Di halaman detail kunci, klik tab Key Material, lalu klik Delete Key Material.

  2. Unduh ulang kunci publik pembungkus dan token impor. Untuk informasi selengkapnya, lihat Langkah 2: Unduh kunci publik pembungkus dan token impor.

    Catatan

    Proses pembungkusan kunci tidak memengaruhi konten bahan kunci. Anda dapat menggunakan kunci publik pembungkus dan algoritma pembungkus yang berbeda untuk mengimpor bahan kunci yang sama.

  3. Gunakan kunci publik pembungkus untuk mengenkripsi bahan kunci. Untuk informasi selengkapnya, lihat Langkah 3: Gunakan kunci publik pembungkus untuk mengenkripsi bahan kunci.

    Catatan

    Bahan kunci harus sama dengan bahan kunci yang kedaluwarsa.

  4. Impor bahan kunci terenkripsi menggunakan token impor. Untuk informasi selengkapnya, lihat Langkah 4: Impor bahan kunci.

Bagaimana cara menentukan apakah bahan kunci diimpor atau dihasilkan oleh KMS?

  • Metode 1: Periksa konsol KMS.

    Di halaman Keys, klik tab Customer Master Keys, pilih Instance ID, temukan kunci target, lalu klik Details di kolom Actions. Di halaman detail, Anda dapat melihat Key Material Source.

  • Metode 2: Panggil operasi DescribeKey.

    Jika nilai Origin adalah EXTERNAL, bahan kunci diimpor. Jika nilai Origin adalah Aliyun_KMS, bahan kunci dihasilkan oleh KMS.

Bagaimana cara memutar kunci yang menggunakan bahan kunci eksternal?

  • Untuk kunci simetris yang dilindungi perangkat lunak yang menggunakan bahan kunci yang diimpor, hanya rotasi manual segera yang didukung, bukan rotasi periodik otomatis. Untuk informasi selengkapnya, lihat Putar kunci Bring-Your-Own-Key (BYOK).

  • Rotasi tidak didukung untuk kunci asimetris yang dilindungi perangkat lunak yang menggunakan bahan kunci yang diimpor.

  • Rotasi tidak didukung untuk kunci yang dilindungi perangkat keras (baik simetris maupun asimetris) yang menggunakan bahan kunci yang diimpor.

Referensi