カスタマーマスタキー (CMK) の説明と分類

カスタマーマスターキー (CMK) は KMS の基本リソースです。 CMK は、キー ID、基本的なメタデータ(キーステータスなど)、およびデータの暗号化と復号化に使用されるキーマテリアルで構成されています。 通常、CreateKeyを実行すると KMS はキーマテリアルを生成します。 外部キーマテリアルからキーを作成することができます。 このような場合、KMS は作成した CMK のキーマテリアルを生成せず、独自のキーマテリアルを CMK にインポートできます。 DescribeKeyを使用して、キーマテリアルのソースを特定することができます。 KeyMetadata 内のオリジンが Aliyun_KMS の場合、KMS によってキーマテリアルが生成され、ノーマルキー ととして参照できることを示します。 Origin が EXTERNAL の場合、キーマテリアルが外部ソースからインポートされ、外部キー として参照できることを示します。

注意事項

外部キーマテリアルソースを選択し、インポートしたキーマテリアルを使用する場合は、次の点に注意する必要があります。

  • キーマテリアルの生成に使用されるランダムソースが要件を満たしていることを確認する必要があります。
  • キーマテリアルの信頼性を保証する必要があります。
    • KMS はインポートされたキーマテリアルの高可用性を保証しますが、インポートされたキーマテリアルが KMS によって生成されたキーマテリアルと同じ信頼性を持つことを保証することはできません。
    • 直接DeleteKeyMaterialを操作して、インポートされたキーマテリアルを削除できます。 または、有効期限切れ後にインポートしたキーマテリアルを CMK を削除せずに自動的に削除する有効期限を設定することもできます。 KMS によって生成されるキーマテリアルは、直接削除することはできません。 代わりに、ScheduleKeyDeletionを使用して、7 〜 30 日後に CMK と共にキーマテリアルを削除できます。
    • インポートされたキーマテリアルを削除した後、同じキーマテリアルを再インポートして、関連する CMK を再び利用可能にすることができます。 従って、キーマテリアルのコピーを個別に保存する必要があります。
  • 各 CMK は、インポートされたキーマテリアルを 1 つだけ持つことができます。 キーマテリアルを CMK にインポートすると、この CMK はこのキーマテリアルにバインドされます。 このキーマテリアルが有効期限切れか、または削除された場合でも、この CMK に他のキーマテリアルをインポートすることはできません。 外部キーマテリアルを使用する CMK をローテーションする必要がある場合、新しい CMK を作成して新しいキーマテリアルをインポートする必要があります。
  • それぞれの CMK は独立したものです。 ある CMK を使用してデータを暗号化する場合、同じキーマテリアルを使用していたとしても、別の CMKを使用してデータを復号化することはできません。
  • キーマテリアルとしてインポートできるのは、256 ビットの対称キーのみです。

キーマテリアルのインポート方法

  1. 外部キーを作成する

    まず、外部キー を作成する必要があります。 これを行うには、コンソールのキー作成の詳細設定オプションに移動し、外部キーマテリアルソースを選択するか、または CreateKey API にリクエストを送信し Origin パラメーター値を EXTERNAL に指定します。 外部キーを作成することを選択することで、このドキュメントの「注意事項」および「キーマテリアルのインポート方法」のセクションを読んで理解したことになります。

    aliyuncli kms CreateKey --Origin EXTERNAL --Description "External key"
    					
  2. インポートキーマテリアルパラメーターを取得する

    外部キーを正常に作成した後、キーマテリアルをインポートする前に、インポートキーマテリアルパラメーターを取得する必要があります。 インポートキーマテリアルパラメーターは、コンソールで取得するか、または、GetParametersForImportにリクエストを送信することによって取得できます。 インポートキーマテリアルのパラメーターには、キーマテリアルを暗号化するために使用される公開キーとインポートトークンが含まれます。

    aliyuncli kms GetParametersForImport --KeyId 1339cb7d-54d3-47e0-b595-c7d3dba82b6f --WrappingAlgorithm RSAES_OAEP_SHA_1 --WrappingKeySpec RSA_2048
    					
  3. キーマテリアルのインポート

    キーマテリアルのインポート操作で、キーマテリアルがない外部キーにキーマテリアルをインポートできます。 また、有効期限切れかまたは削除されたキーマテリアルを再インポートすることも、キーマテリアルの有効期限を再設定することもできます。 インポートトークンは、キーマテリアルを暗号化するために使用される公開キーにバインドされています。 単一のトークンは、生成時に指定された CMK のキーマテリアルをインポートするためにのみ使用できます。 インポートトークンは 24 時間有効で、この期間中は複数回使用できます。 トークンが有効期限切れになったら、新しいインポートトークンと公開暗号キーを取得する必要があります。

    • まず、公開暗号キーを使用してキーマテリアルを暗号化します。 公開暗号鍵は 2,048 ビットの RSA 公開鍵です。 使用される暗号化アルゴリズムは、インポートキーマテリアルパラメーターを取得するときに指定されたものと同じでなければなりません。 API は base64 エンコードで公開暗号キーを返すので、使用するときはまず base64 デコードを実行する必要があります。 現在、KMS は、RSAES_OAEP_SHA_1、RSAES_OAEP_SHA_256、および RSAES_PKCS1_V1_5 という暗号化アルゴリズムをサポートしています。
    • 暗号化の後、暗号化されたキーマテリアルに対して base64 エンコードを実行し、これをキーマテリアルを KMS にインポートするためのGenerateDataKeyパラメーターとしてインポートトークンと共に使用する必要があります。

    aliyuncli kms ImportKeyMaterial --KeyId 1339cb7d-54d3-47e0-b595-c7d3dba82b6f --EncryptedKeyMaterial xxx --ImportToken xxxx
    					

キーマテリアルの削除

  • キーマテリアルをインポートした後、ノーマルキーのように外部キーを使用することができます。 外部キーは、そのキーマテリアルの有効期限が切れたり手動で削除される可能性があるという点で通常のキーとは異なります。 キーマテリアルの有効期限が切れたり削除されると、キーは機能しなくなり、このキーを使用して暗号化された暗号テキストデータは、同じキーマテリアルを再インポートしない限り復号化できません。
  • キーマテリアルの有効期限が切れるか、または削除された後に、キーが Pen-USdingDeletion 状態になると、キーの状態は変更されません。 それ以外の場合は、キーの状態は PendingImport に変わります。
  • コンソールまたはDeleteKeyMaterialを使って、キーマテリアルを削除できます。

aliyuncli kms DeleteKeyMaterial --KeyId xxxx
			

操作例

OPENSSL を使用してキーマテリアルの暗号化およびアップロード

  • 外部キーを作成します。
  • キーマテリアルを生成します。 キーマテリアルは 256 ビットの対称キーでなければなりません。 この例では、OPENSSL を使用して 32 バイトの乱数を生成します。
    1.openssl rand -out KeyMaterial.bin 32
  • インポートキーマテリアルパラメーターを取得します。
  • キーマテリアルを暗号化します。
  • まず、公開暗号鍵で base64 デコードを実行する必要があります。
  • 次に、暗号化アルゴリズム (ここではRSAES_OAEP_SHA_1 を使用) を使用してキーマテリアルを暗号化します。
  • 最後に、暗号化されたキーマテリアルに対して base64 エンコードを実行し、テキストファイルとして保存します。
    openssl rand -out KeyMaterial.bin 32
    openssl enc -d -base64 -A -in PublicKey_base64.txt -out PublicKey.bin
    openssl rsautl -encrypt -in KeyMaterial.bin -oaep -inkey PublicKey.bin  -keyform DER  -pubin -out EncryptedKeyMaterial.bin
    openssl enc -e -base64 -A -in EncryptedKeyMaterial.bin -out EncryptedKeyMaterial_base64.txt
  • 暗号化されたキーマテリアルとインポートトークンをアップロードします。

JAVA SDK を使用してキーマテリアルの暗号化およびアップロードする

//Uses the latest KMS JAVA SDK
//KmsClient.java

import com.aliyuncs.kms.model.v20160120.*;
import com.aliyuncs.profile.DefaultProfile;

//KMS API encapsulation
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"); //Creates an external key
                return this.client.getAcsResponse(request);
        }
        //... Omitted, the remaining operations are the same as those in the API method.
}
//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 = "*** Provide your AccessKeyId ***";
        String accessKeySecret = "*** Provide your AccessKeySecret ***";
        KmsClient kmsclient = new KmsClient(regionId,accessKeyId,accessKeySecret);
        //Create External Key
        try {
                CreateKeyResponse keyResponse = kmsclient.createKey();
                String keyId = keyResponse.KeyMetadata.getKeyId();
                //Generates a 32-bit random number
                byte[] keyMaterial = new byte[32];
                new Random().nextBytes(keyMaterial);
                //Gets import key material parameters
                GetParametersForImportResponse paramResponse = kmsclient.getParametersForImport(keyId,"RSAES_OAEP_SHA_256");
                String importToekn = paramResponse.getImportToken();
                String encryptPublicKey = paramResponse.getPublicKey();
                //Performs base64 decoding on the public encryption key
                byte[] publicKeyDer = DatatypeConverter.parseBase64Binary(encryptPublicKey);
                //Parses the RSA public key
                KeyFactory keyFact = KeyFactory.getInstance("RSA");
                X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyDer);
                PublicKey publicKey = keyFact.generatePublic(spec);
                //Encrypts 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);
                //You must perform base64 encoding on the encrypted key material
                String encryptedKeyMaterial = DatatypeConverter.printBase64Binary(cipherDer);
                //Imports key material
                Long expireTimestamp = 1546272000L; //Unix timestamp, precise to the second, 0 indicates no expiration
                        kmsClient.importKeyMaterial(keyId,encryptedKeyMaterial, expireTimestamp);
        } catch(Exception e) {
                //... Omitted
        }
        }
}