外部キーマテリアルソースを持つ顧客マスターキー (CMK) を作成する場合、キー管理サービス (KMS) はキーマテリアルを作成しません。 この場合、外部キーマテリアルをCMKにインポートする必要があります。 このトピックでは、外部キーマテリアルをインポートする方法について説明します。
背景情報
CMKはKMSの基本リソースです。 CMKは、キーID、キーステータスなどのメタデータ、およびデータの暗号化と復号化に使用されるキーマテリアルで構成されます。 CMKの作成時にOriginパラメーターのデフォルト値Aliyun_KMSを使用すると、KMSはキーマテリアルを生成します。 OriginパラメーターをEXTERNALに設定した場合、KMSはキーマテリアルを生成しません。 この場合、外部キーマテリアルをCMKにインポートする必要があります。
外部CMKにインポートされたことがない、または期限切れまたは削除されたキーマテリアルをインポートできます。 キーマテリアルの有効期限をリセットすることもできます。
DescribeKey操作を呼び出して、既存のCMKのキーマテリアルソースを確認できます。
KeyMetadataのOriginパラメーターの値がAliyun_KMSの場合、キーマテリアルはKMSによって生成されます。 この場合、CMKは通常のCMKと見なされます。
Originパラメーターの値がEXTERNALの場合、キーマテリアルは外部ソースからインポートされます。 この場合、CMKは外部CMKと見なされます。
外部キーマテリアルをインポートするときは、次の点に注意してください。
キーマテリアルが生成されるランダム性のソースがセキュリティ要件を満たしていることを確認します。
キー材料が信頼できることを確かめて下さい。
KMSは、インポートされたキーマテリアルの高可用性を保証します。 ただし、KMSは、インポートされたキーマテリアルがKMSによって生成されたキーマテリアルと同じ信頼性を持つことを保証できません。
インポートしたキーマテリアルをCMKから削除した後、同じキーマテリアルを再インポートして、CMKを再度使用可能にすることができます。 したがって、キーマテリアルのコピーを保存することをお勧めします。
DeleteKeyMaterial操作を呼び出して、インポートしたキーマテリアルを削除できます。 有効期間を設定して、有効期間の終了後にKMSがキーマテリアルを自動的に削除できるようにすることもできます。 CMKは削除されません。
CMKは1つのキーマテリアルのみを持つことができます。 キーマテリアルをCMKにインポートすると、CMKはキーマテリアルにバインドされます。 キーマテリアルが期限切れまたは削除された後でも、別のキーマテリアルをそのCMKにインポートすることはできません。 外部キーマテリアルを使用するCMKを回転させる必要がある場合は、CMKを作成してから新しいキーマテリアルをインポートする必要があります。
それぞれの CMK は独立したものです。 2つのCMKが同じキーマテリアルを使用する場合でも、CMKを使用して別のCMKを使用して暗号化されたデータを復号化することはできません。
インポートできるキーマテリアルは、256ビットの対称AESキーである必要があります。
KMSコンソールでのキーマテリアルのインポート
外部CMKを作成します。
KMSコンソールにログインします。 上部のナビゲーションバーで、外部CMKを作成するリージョンを選択します。
左側のナビゲーションウィンドウで、キーをクリックします。
[キーの作成] をクリックします。 [キーの作成] ダイアログボックスで、パラメーターを設定します。
パラメーター
説明
KMSインスタンス
使用するKMSインスタンス。 デフォルト値defaultを保持します。 パラメーターの値は変更できません。
キー仕様
CMKのタイプ。 パラメーターをAliyun_AES_256に設定します。 対称CMKの種類の詳細については、「概要」をご参照ください。
目的
CMKの使用法。 有効な値:
Encrypt/Decrypt: データを暗号化または復号します。
署名 /検証: データに署名するか、デジタル署名を検証します。
エイリアス名
CMKの識別子。 名前には、英数字、アンダースコア (_) 、ハイフン (-) 、およびスラッシュ (/) を使用できます。
詳細については、「概要」をご参照ください。
保護レベル
CMKの保護レベル。 有効な値:
ソフトウェア: CMKはソフトウェアモジュールを使用して保護されます。
Hsm: CMKはハードウェアセキュリティモジュール (HSM) で管理され、HSMはCMKを保護します。
説明
CMK の説明。
ローテーション期間
CMKの自動回転間隔。
説明このパラメーターは、Key SpecパラメーターをAliyun_AES_256に設定した場合にのみ設定できます。
重要な材料ソース
キー素材のソース。 [外部] を選択します。
外部キーマテリアルキーを使用することの意味を理解していますを選択し、OKをクリックします。
キーマテリアルのインポートに使用されるパラメータを取得します。
パラメータには、公開鍵およびインポートトークンが含まれる。 公開鍵は、鍵材料を暗号化するために使用される。
左側のナビゲーションウィンドウで、キーをクリックします。
キーマテリアルをインポートするCMKのIDをクリックして、キー管理ページに移動します。 [キーマテリアル] セクションで、[キーマテリアルのインポートに使用するパラメーターの取得] をクリックします。
キーマテリアルのインポートに使用されるパラメータの取得ダイアログボックスで、ラッピングキータイプパラメータと、ラッピングアルゴリズムパラメーターを設定し、次へをクリックします。
この例では、[ラッピングキータイプ] パラメーターをRSA_2048に設定し、[ラッピングアルゴリズム] パラメーターをRSAES_OAEP_SHA_1に設定します。
説明ラッピングキータイプパラメーターをRSA_2048に設定した場合、ラッピングアルゴリズムパラメーターをRSAES_PKCS1_V1_5、RSAES_OAEP_SHA_1、またはRSAES_OAEP_SHA_256に設定できます。 デフォルト値はRSAES_PKCS1_V1_5です。
公開鍵とインポートトークンをダウンロードします。 次に、[閉じる] をクリックします。
公開鍵をダウンロードする前に、公開鍵形式の値を選択する必要があります。
[公開鍵形式] に [DER形式] を選択した場合、ダウンロードした公開鍵ファイルのサフィックスは. binです。 例: publickey_f240b730-7e3e-4bd7-877f-4fe22524 ****.bin。
[公開鍵形式] に [PEM形式] を選択した場合、ダウンロードした公開鍵ファイルのサフィックスは. pemです。 例: publickey_f240b730-7e3e-4bd7-877f-4fe22524 ****.pem。
キー素材を暗号化します。
公開鍵とインポートトークンをダウンロードした後、公開鍵を使用してキーマテリアルを暗号化できます。
次の手順では、OpenSSLを使用してキーマテリアルを暗号化する方法について説明します。 暗号化アルゴリズムは、キーマテリアルのインポートに使用されるパラメーターを取得するときに指定するアルゴリズムと同じである必要があります。 この例では、アルゴリズムRSAES_OAEP_SHA_1が使用されます。
OpenSSLを使用して32バイトの乱数を生成します。 番号はキーマテリアルとして使用されます。
openssl rand -out KeyMaterial.bin 32
指定された暗号化アルゴリズムを使用して、キーマテリアルを暗号化します。
次のサンプルコードを実行する前に、次の項目に注意してください。
サンプルコードのPublicKey.binを、「キーマテリアルのインポートに使用されるパラメーターの取得」でダウンロードした公開キーファイルの名前に置き換えます。
サンプルコードでは、指定された公開鍵ファイルはDER形式です。 公開キーをダウンロードするときにPEM形式を選択した場合、サンプルコードの
-keyform DER
を-keyform PEM
に置き換える必要があります。
openssl rsautl -encrypt -in KeyMaterial.bin -oaep -inkey PublicKey.bin -keyform DER -pubin -out EncryptedKeyMaterial.bin
暗号化されたキーマテリアルをBase64でエンコードし、テキストファイルに保存します。
openssl enc -e -base64 -A -in EncryptedKeyMaterial.bin -out EncryptedKeyMaterial_base64.txt
キーマテリアルをインポートします。
各インポートトークンは、キーマテリアルの暗号化に使用される公開キーにバインドされます。 CMKは、インポートトークンが生成されるときに指定されます。 インポートトークンは、指定されたCMKのキーマテリアルのみをインポートするために使用できます。 インポートトークンの有効期間は24時間です。 トークンは、この期間内に繰り返し使用することができる。 トークンの有効期限が切れたら、新しいインポートトークンと新しい公開キーを取得する必要があります。
左側のナビゲーションウィンドウで、キーをクリックします。
キーマテリアルをインポートするCMKのIDをクリックして、キー管理ページに移動します。 [キーマテリアル] セクションで、[ラップキーマテリアルのインポート] をクリックします。
ラップキー素材のインポートダイアログボックスで、包まれたキー材料とトークンのインポートパラメーターを設定します。
ラップされたキー素材: キー素材の暗号化で生成され、キー素材を含むテキストファイルをアップロードします。
[トークンのインポート]: [キーマテリアルのインポートに使用されるパラメーターの取得] で取得した、インポートトークンを含むテキストファイルをアップロードします。
有効期限パラメーターを設定し、OKをクリックします。
キーマテリアルがインポートされると、CMKのステータスが [Pending Import] から [Enabled] に変わります。
Alibaba Cloud CLIを使用したキーマテリアルのインポート
外部CMKを作成します。
aliyun kms CreateKeyコマンドを実行し、CreateKey操作を呼び出して外部CMKを作成し、Originパラメーターをexternalに設定します。
aliyun kms CreateKey --Origin EXTERNAL --Description "External key"
キーマテリアルのインポートに使用されるパラメータを取得します。
aliyun kms GetParametersForImportコマンドを実行し、GetParametersForImport操作を呼び出して、キーマテリアルのインポートに使用されるパラメーターを取得します。
aliyun kms GetParametersForImport --KeyId 1339cb7d-54d3-47e0-b595-c7d3dba8**** --WrappingAlgorithm RSAES_OAEP_SHA_1 --WrappingKeySpec RSA_2048
キーマテリアルをインポートします。
公開鍵を使用してキーマテリアルを暗号化します。
公開鍵は、2,048ビットのRivest-Shamir-Adleman (RSA) 公開鍵である。 暗号化アルゴリズムは、キーマテリアルのインポートに使用されるパラメーターを取得するときに指定されたものと同じである必要があります。 GetParametersForImport操作によって返される公開キーは、Base64でエンコードされます。 最初に公開鍵をデコードする必要があります。 KMSは、RSAES_OAEP_SHA_1、RSAES_OAEP_SHA_256、およびRSAES_PKCS1_V1_5の暗号化アルゴリズムをサポートしています。
暗号化されたキーマテリアルをBase64でエンコードします。
キーマテリアルとインポートトークンをImportKeyMaterial操作にパラメーターとして渡します。 aliyun kms ImportKeyMaterialコマンドを実行して、エンコードされたキーマテリアルをKMSにインポートします。
aliyun kms ImportKeyMaterial --KeyId 1339cb7d-54d3-47e0-b595-c7d3dba8**** --EncryptedKeyMaterial xxx --ImportToken xxxx --KeyMaterialExpireUnix xxxx
KMS SDKを使用したキーマテリアルのインポート
サンプルコード:
JAVA SDK
説明Alibaba CloudアカウントのAccessKeyペアには、すべてのAPI操作に対する権限があります。 AccessKeyペアを使用して操作を実行することは、リスクの高い操作です。 RAMユーザーを使用してAPI操作を呼び出したり、ルーチンのO&Mを実行することを推奨します。プロジェクトコードにAccessKey IDとAccessKey Secretを保存しないことを推奨します。 そうしないと、AccessKeyペアが漏洩し、アカウントに属するすべてのリソースのセキュリティが侵害される可能性があります。
この例では、AccessKeyペアは、ID認証を実装するためにALIBABA_CLOUD_ACCESS_KEY_IDとALIBABA_CLOUD_ACCESS_KEY_SECRET環境変数に保存されます。
認証情報の設定方法の詳細については、「アクセス資格情報の管理」をご参照ください。
環境変数を設定するために使用される方法は、オペレーティングシステムによって異なります。 詳細については、「Linux、macOS、およびWindowsでの環境変数の設定」をご参照ください。
// Use the latest version of KMS SDK for Java. //KmsClient.java import com.aliyuncs.kms.model.v20160120.*; import com.aliyuncs.profile.DefaultProfile; // Encapsulate the CreateKey operation. public class KmsClient { DefaultAcsClient client; public KmsClient( String region_id, String ak, String secret) { DefaultProfile profile = DefaultProfile.getProfile(region_id, ak, secret); this.client = new DefaultAcsClient(profile); } public CreateKeyResponse createKey() throws Exception { CreateKeyRequest request = new CreateKeyRequest(); request.setOrigin("EXTERNAL"); // Create an external CMK. return this.client.getAcsResponse(request); } //.Omitted. The method that is used to encapsulate other operations is similar to the method that is used to encapsulate the preceding operation. } //example.java import com.aliyuncs.kms.model.v20160120.*; import KmsClient; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.MGF1ParameterSpec; import javax.crypto.Cipher; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource.PSpecified; import java.security.spec.X509EncodedKeySpec; import java.util.Random; import javax.xml.bind.DatatypeConverter; public class CreateAndImportExample { public static void main(String[] args) { String regionId = "cn-hangzhou"; String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"); String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"); KmsClient kmsclient = new KmsClient(regionId,accessKeyId,accessKeySecret); // Create an external CMK. try { CreateKeyResponse keyResponse = kmsclient.createKey(); String keyId = keyResponse.KeyMetadata.getKeyId(); // Generate a 32-byte random number. byte[] keyMaterial = new byte[32]; new Random().nextBytes(keyMaterial); // Obtain the parameters that are used to import key material. GetParametersForImportResponse paramResponse = kmsclient.getParametersForImport(keyId,"RSAES_OAEP_SHA_256"); String importToekn = paramResponse.getImportToken(); String encryptPublicKey = paramResponse.getPublicKey(); // Decode the public key in Base64. byte[] publicKeyDer = DatatypeConverter.parseBase64Binary(encryptPublicKey); // Generate an RSA public key. KeyFactory keyFact = KeyFactory.getInstance("RSA"); X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyDer); PublicKey publicKey = keyFact.generatePublic(spec); // Encrypt the key material. Cipher oaepFromAlgo = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"); String hashFunc = "SHA-256"; OAEPParameterSpec oaepParams = new OAEPParameterSpec(hashFunc, "MGF1", new MGF1ParameterSpec(hashFunc), PSpecified.DEFAULT); oaepFromAlgo.init(Cipher.ENCRYPT_MODE, publicKey, oaepParams); byte[] cipherDer = oaepFromAlgo.doFinal(keyMaterial); // Encode the encrypted key material in Base64. String encryptedKeyMaterial = DatatypeConverter.printBase64Binary(cipherDer); // Import the key material. Long expireTimestamp = 1546272000L; // The UNIX timestamp, which is accurate to the second. A value of 0 indicates that the key material does not expire. kmsclient.importKeyMaterial(keyId,encryptedKeyMaterial, expireTimestamp); } catch(Exception e) { //... Omitted. } } }
Go SDK
説明Alibaba CloudアカウントのAccessKeyペアには、すべてのAPI操作に対する権限があります。 AccessKeyペアを使用して操作を実行することは、リスクの高い操作です。 RAMユーザーを使用してAPI操作を呼び出したり、ルーチンのO&Mを実行することを推奨します。プロジェクトコードにAccessKey IDとAccessKey Secretを保存しないことを推奨します。 そうしないと、AccessKeyペアが漏洩し、アカウントに属するすべてのリソースのセキュリティが侵害される可能性があります。
この例では、AccessKeyペアは、ID認証を実装するためにALIBABA_CLOUD_ACCESS_KEY_IDとALIBABA_CLOUD_ACCESS_KEY_SECRET環境変数に保存されます。
認証情報を設定する方法の詳細については、「SDKクライアントの初期化とAPIリクエストの送信」をご参照ください。
環境変数を設定するために使用される方法は、オペレーティングシステムによって異なります。 詳細については、「Linux、macOS、およびWindowsでの環境変数の設定」をご参照ください。
package main import ( "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/base64" "fmt" "log" random "math/rand" "time" "github.com/aliyun/alibaba-cloud-sdk-go/services/kms" ) // Encapsulate the CreateKey operation. func kmsCreateKey(client *kms.Client) (string, error) { request := kms.CreateCreateKeyRequest() request.Scheme = "https" request.Origin = "EXTERNAL" // Create an external CMK. response, err := client.CreateKey(request) if err != nil { return "", fmt.Errorf("CreateKey error:%v", err) } return response.KeyMetadata.KeyId, nil } // Encapsulate the GetParametersForImport operation. func kmsGetParametersForImport(client *kms.Client, keyId, wrappingKeySpec, wrappingAlgorithm string) (string, string, error) { request := kms.CreateGetParametersForImportRequest() request.Scheme = "https" request.KeyId = keyId request.WrappingKeySpec = wrappingKeySpec request.WrappingAlgorithm = wrappingAlgorithm response, err := client.GetParametersForImport(request) if err != nil { return "", "", fmt.Errorf("GetParametersForImport error:%v", err) } return response.PublicKey, response.ImportToken, nil } // Encapsulate the ImportKeyMaterial operation. func kmsImportKeyMaterial(client *kms.Client, keyId, importToken, encryptedKeyMaterial string) error { request := kms.CreateImportKeyMaterialRequest() request.Scheme = "https" request.KeyId = keyId request.ImportToken = importToken request.EncryptedKeyMaterial = encryptedKeyMaterial _, err := client.ImportKeyMaterial(request) if err != nil { return fmt.Errorf("ImportKeyMaterial error:%v", err) } return nil } func randBytes(n int) []byte { var r = random.New(random.NewSource(time.Now().UnixNano())) bytes := make([]byte, n) for i := range bytes { bytes[i] = byte(r.Intn(256)) } return bytes } func main() { accessKeyId := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID") accessKeySecret := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET") regionId := "cn-hangzhou" client, err := kms.NewClientWithAccessKey(regionId, accessKeyId, accessKeySecret) if err != nil { log.Fatalf("NewClientWithAccessKey error:%+v\n", err) } // Create an external CMK. keyId, err := kmsCreateKey(client) if err != nil { log.Fatalf("kmsCreateKey error:%+v\n", err) } // The following sample code is used to generate a 32-byte random number. In actual scenarios, you must generate a key in your own key management system. Then, you must use the public key in the parameters that are used to import key material to encrypt the key material. keyMaterial := randBytes(32) // Obtain the parameters that are used to import key material. encryptPublicKey, importToken, err := kmsGetParametersForImport(client, keyId, "RSA_2048", "RSAES_OAEP_SHA_256") if err != nil { log.Fatalf("kmsGetParametersForImport error:%v\n", err) } // Decode the public key in Base64. publicKeyDer, err := base64.StdEncoding.DecodeString(encryptPublicKey) if err != nil { log.Fatalf("base64.StdEncoding.DecodeString error:%v\n", err) } // Generate an RSA public key. publicKey, err := x509.ParsePKIXPublicKey(publicKeyDer) if err != nil { log.Fatalf("x509.ParsePKIXPublicKey error:%v\n", err) } // Encrypt the key material. cipherDer, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey.(*rsa.PublicKey), keyMaterial, nil) if err != nil { log.Fatalf("rsa.EncryptOAEP error:%v\n", err) } // Encode the encrypted key material in Base64. encryptedKeyMaterial := base64.StdEncoding.EncodeToString(cipherDer) // Import the key material. err = kmsImportKeyMaterial(client, keyId, importToken, encryptedKeyMaterial) if err != nil { log.Fatalf("ImportKeyMaterial error:%v", err) } }