このトピックでは、Java用のKey Management Service (KMS) SDKの使用例を示します。
背景情報
オープンソースコードリポジトリにアクセスして、さまざまなシナリオのさまざまなプログラミング言語のKMS SDKのサンプルコードを表示できます。 コメントを共有するか、サンプルコードを提供することを歓迎します。
KMSのAPI操作の詳細については、「関数別の操作の一覧」をご参照ください。
準備
KMS SDK for Javaの依存関係宣言を取得します。 必要なSDKバージョンの詳細については、「SDKの概要」をご参照ください。 例:
<dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.5.2</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-kms</artifactId> <version>2.15.0</version> </dependency>
KMSの領域に基づいてKMSのエンドポイントを取得します。 詳細については、「Make API requests」をご参照ください。
説明KMSのリージョンIDのみを指定すると、そのリージョンのKMSのパブリックエンドポイントが自動的に使用されます。
仮想プライベートクラウド (VPC) 経由でKMSにアクセスする場合は、KMSのVPCアドレスを指定する必要があります。
例1: パブリックエンドポイントまたはVPCアドレスを介したKMSへのアクセス
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での環境変数の設定」をご参照ください。
カプセル化されたクラスを呼び出してKMSクライアントを作成します。
説明暗号化するデータに特殊文字
<>&
が含まれている場合は、FormatTypeをXMLに設定してデータを復号化することを推奨します。 これは、復号化中に特殊文字がエスケープされるときに発生するエラーを防ぐのに役立ちます。 たとえば、decReq.setAcceptFormat(FormatType.XML)
を指定します。package com.aliyun.kms.samples; import java.util.*; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.http.*; //Current KMS SDK version:2016-01-20 import com.aliyuncs.kms.model.v20160120.*; import com.aliyuncs.kms.model.v20160120.ListKeysResponse.Key; import com.aliyuncs.profile.*; public class KmsClient { private DefaultAcsClient kmsClient; /** * Create a KMS client. You need to only specify the region ID of KMS. KMS SDK for Java automatically obtains the public endpoint of KMS for the region. */ public static KmsClient 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 new KmsClient(client); } /** * Create a KMS client. You can specify a VPC address that is used to access KMS. */ public static KmsClient getClientForVpcEndpoint(String regionId, String accessKeyId, String accessKeySecret, String endpoint) { // Specify a VPC address. DefaultProfile.addEndpoint(regionId, "kms", endpoint); IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret); HttpClientConfig clientConfig = HttpClientConfig.getDefault(); profile.setHttpClientConfig(clientConfig); DefaultAcsClient client = new DefaultAcsClient(profile); return new KmsClient(client); } private KmsClient(DefaultAcsClient acsClient) { this.kmsClient = acsClient; } public CreateKeyResponse CreateKey(String keyDesc, String keyUsage) throws ClientException { final CreateKeyRequest ckReq = new CreateKeyRequest(); ckReq.setProtocol(ProtocolType.HTTPS); ckReq.setAcceptFormat(FormatType.JSON); ckReq.setMethod(MethodType.POST); ckReq.setDescription(keyDesc); ckReq.setKeyUsage(keyUsage); final CreateKeyResponse response = kmsClient.getAcsResponse(ckReq); return response; } public DescribeKeyResponse DescribeKey(String keyId) throws ClientException { final DescribeKeyRequest decKeyReq = new DescribeKeyRequest(); decKeyReq.setProtocol(ProtocolType.HTTPS); decKeyReq.setAcceptFormat(FormatType.JSON); decKeyReq.setMethod(MethodType.POST); decKeyReq.setKeyId(keyId); final DescribeKeyResponse decKeyRes = kmsClient.getAcsResponse(decKeyReq); return decKeyRes; } public ListKeysResponse ListKey(int pageNumber, int pageSize) throws ClientException { final ListKeysRequest listKeysReq = new ListKeysRequest(); listKeysReq.setProtocol(ProtocolType.HTTPS); listKeysReq.setAcceptFormat(FormatType.JSON); listKeysReq.setMethod(MethodType.POST); listKeysReq.setPageNumber(pageNumber); listKeysReq.setPageSize(pageSize); final ListKeysResponse listKeysRes = kmsClient.getAcsResponse(listKeysReq); return listKeysRes; } public GenerateDataKeyResponse GenerateDataKey(String keyId, String keyDesc, int numOfBytes) throws ClientException { final GenerateDataKeyRequest genDKReq = new GenerateDataKeyRequest(); genDKReq.setProtocol(ProtocolType.HTTPS); genDKReq.setAcceptFormat(FormatType.JSON); genDKReq.setMethod(MethodType.POST); /** * Set parameter according to KMS openAPI document: * 1.KeyId * 2.KeyDescription * 3.NumberOfBytes */ genDKReq.setKeySpec(keyDesc); genDKReq.setKeyId(keyId); genDKReq.setNumberOfBytes(numOfBytes); final GenerateDataKeyResponse genDKRes = kmsClient.getAcsResponse(genDKReq); return genDKRes; } public EncryptResponse Encrypt(String keyId, String plainText) throws ClientException { final EncryptRequest encReq = new EncryptRequest(); encReq.setProtocol(ProtocolType.HTTPS); encReq.setAcceptFormat(FormatType.JSON); encReq.setMethod(MethodType.POST); encReq.setKeyId(keyId); encReq.setPlaintext(plainText); final EncryptResponse encResponse = kmsClient.getAcsResponse(encReq); return encResponse; } public DecryptResponse Decrypt(String cipherBlob) throws ClientException { final DecryptRequest decReq = new DecryptRequest(); decReq.setProtocol(ProtocolType.HTTPS); decReq.setAcceptFormat(FormatType.JSON); decReq.setMethod(MethodType.POST); decReq.setCiphertextBlob(cipherBlob); final DecryptResponse decResponse = kmsClient.getAcsResponse(decReq); return decResponse; } }
KMSクライアントを使用して、キーの列挙、データの暗号化、データの復号化などの操作を呼び出します。
説明次のサンプルコードでは、Alibaba Cloudアカウントに中国 (杭州) リージョンに少なくとも1つのKMSカスタマーマスターキー (CMK) があります。
KmsClient.getClientForPublicEndpoint
メソッドは、KMSのパブリックエンドポイントを返します。KmsClient.getClientForVpcEndpoint
メソッドは、KMSのVPCアドレスを返します。
package com.aliyun.kms.samples; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.exceptions.ServerException; import com.google.gson.Gson; import java.util.*; import com.aliyuncs.kms.model.v20160120.*; import com.aliyuncs.kms.model.v20160120.ListKeysResponse.Key; public class KmsSample { public static void main(String[] args) { String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"); String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"); KmsClient kmsClient = KmsClient.getClientForPublicEndpoint("cn-hangzhou", accessKeyId, accessKeySecret); //KmsClient kmsClient = KmsClient.getClientForVpcEndpoint("cn-hangzhou-vpc", accessKeyId, accessKeySecret, "kms-vpc.cn-hangzhou.aliyuncs.com"); String keyId = null; String plainText = "hello world"; String cipherBlob = null; /*List all MasterKeys in your account*/ try { final ListKeysResponse listKeysRes = kmsClient.ListKey(1, 100); /** * Parse response and do more further */ System.out.println("TotalCount: " + listKeysRes.getTotalCount()); System.out.println("PageNumber: " + listKeysRes.getPageNumber()); System.out.println("PageSize: " + listKeysRes.getPageSize()); List<Key> keys = listKeysRes.getKeys(); Iterator<Key> iterator = keys.iterator(); while (iterator.hasNext()) { keyId = iterator.next().getKeyId(); System.out.println("KeyId: " + keyId); } System.out.println("List All MasterKeys success!\n"); } catch (ClientException eResponse) { System.out.println("Failed."); System.out.println("Error code: " + eResponse.getErrCode()); System.out.println("Error message: " + eResponse.getErrMsg()); } /*Describe the Key */ try { final DescribeKeyResponse decKeyRes = kmsClient.DescribeKey(keyId); /** * Parse response and do more further */ System.out.println("DescribeKey Response: "); DescribeKeyResponse.KeyMetadata meta = decKeyRes.getKeyMetadata(); System.out.println("KeyId: " + meta.getKeyId()); System.out.println("Description: " + meta.getDescription()); System.out.println("KeyState: " + meta.getKeyState()); System.out.println("KeyUsage: " + meta.getKeyUsage()); System.out.println("==========================================="); System.out.println("Describe the MasterKey success!"); System.out.println("===========================================\n"); } catch (ClientException eResponse) { System.out.println("Failed."); System.out.println("Error code: " + eResponse.getErrCode()); System.out.println("Error message: " + eResponse.getErrMsg()); } /*Generate DataKey*/ /** * Request and got response */ try { final GenerateDataKeyResponse genDKResponse = kmsClient.GenerateDataKey(keyId, "AES_256", 64); /** * Parse response and do more further */ System.out.println("CiphertextBlob: " + genDKResponse.getCiphertextBlob()); System.out.println("KeyId: " + genDKResponse.getKeyId()); System.out.println("Plaintext: " + genDKResponse.getPlaintext()); System.out.println("==========================================="); System.out.println("Generate DataKey success!"); System.out.println("===========================================\n"); } catch (ClientException eResponse) { System.out.println("Failed."); System.out.println("Error code: " + eResponse.getErrCode()); System.out.println("Error message: " + eResponse.getErrMsg()); } /** * Encrypt the plain text and got a cipher one */ try { EncryptResponse encResponse = kmsClient.Encrypt(keyId, plainText); cipherBlob = encResponse.getCiphertextBlob(); System.out.println("CiphertextBlob: " + cipherBlob); System.out.println("KeyId: " + encResponse.getKeyId()); System.out.println("==========================================="); System.out.println("Encrypt the plain text success!"); System.out.println("===========================================\n"); } catch (ClientException eResponse) { System.out.println("Failed."); System.out.println("Error code: " + eResponse.getErrCode()); System.out.println("Error message: " + eResponse.getErrMsg()); } /** * Decrypt the cipher text and verify result with original plain text. */ try { DecryptResponse decResponse = kmsClient.Decrypt(cipherBlob); System.out.println("Plaintext: " + decResponse.getPlaintext()); String verifyPlainText = decResponse.getPlaintext(); int isMatch = verifyPlainText.compareTo(plainText); System.out.println("KeyId: " + decResponse.getKeyId()); System.out.println("==========================================="); System.out.printf("Decrypt the cipher text success, result " + (isMatch == 0 ? "match" : "mismatch" + "\n")); System.out.println("===========================================\n"); } catch (ClientException eResponse) { System.out.println("Failed."); System.out.println("Error code: " + eResponse.getErrCode()); System.out.println("Error message: " + eResponse.getErrMsg()); } } }
例2: クライアントキーベースのアプリケーションアクセスポイント (AAP) を使用したSecrets Managerへのアクセス
KMS SDK for Javaを使用して、クライアントキーベースのAAPを使用してSecrets Managerにアクセスする場合は、次のサンプルコードを使用できます。
詳細については、「クライアントキーをAAPにバインドする」をご参照ください。
package com.aliyuncs.kms.sample;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.auth.AlibabaCloudCredentialsProvider;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.kms.clientkey.utils.ClientKeyUtils;
import java.io.IOException;
public class ClientKeySample {
public static void main(String[] args) throws IOException {
String clientKeyPath = "<client-key-file-path>";
String password = System.getenv("<client-key-password-env-name>");
AlibabaCloudCredentialsProvider provider = ClientKeyUtils.getCredentialsProvider(clientKeyPath, password);
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou");
IAcsClient kmsClient = new DefaultAcsClient(profile, provider);
// invoke kmsClient
}
}
上記のサンプルコードは、ClientKeyUtilsおよびClientKeyCredentialsProviderの次のコードを参照しています。
ClientKeyUtils
package com.aliyuncs.kms.clientkey.utils; import com.aliyuncs.auth.AlibabaCloudCredentialsProvider; import com.aliyuncs.kms.auth.ClientKeyCredentialsProvider; import com.aliyuncs.auth.KeyPairCredentials; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import java.io.*; import java.security.*; import java.security.cert.CertificateException; import java.util.Base64; import java.util.Enumeration; public class ClientKeyUtils { private final static String PKCS12 = "PKCS12"; private final static Gson gson = new Gson(); private ClientKeyUtils() { // do nothing } public static AlibabaCloudCredentialsProvider getCredentialsProvider(String clientKeyFileName, String password) throws IOException { try (Reader reader = new InputStreamReader(new FileInputStream(clientKeyFileName), "utf-8")) { ClientKeyInfo clientKeyInfo = gson.fromJson(reader, ClientKeyInfo.class); if (clientKeyInfo != null) { byte[] pk12 = Base64.getDecoder().decode(clientKeyInfo.getPrivateKeyData()); try { String privateKey = getPrivateKeyPemFromPk12(pk12, password); return new ClientKeyCredentialsProvider(new KeyPairCredentials(clientKeyInfo.getKeyId(), privateKey)); } catch (Exception e) { throw new IOException(e); } } else { throw new IOException("ClientKey is invalid"); } } } private static String getPrivateKeyPemFromPk12(byte[] pk12, String password) throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException, UnrecoverableKeyException { KeyStore keyStore = KeyStore.getInstance(PKCS12); keyStore.load(new ByteArrayInputStream(pk12), password.toCharArray()); Enumeration<String> e = keyStore.aliases(); String alias = e.nextElement(); PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray()); return Base64.getEncoder().encodeToString(privateKey.getEncoded()); } } class ClientKeyInfo { @SerializedName("KeyId") private String keyId; @SerializedName("PrivateKeyData") private String privateKeyData; public String getKeyId() { return this.keyId; } public void setKeyId(String keyId) { this.keyId = keyId; } public String getPrivateKeyData() { return this.privateKeyData; } public void setPrivateKeyData(String privateKeyData) { this.privateKeyData = privateKeyData; } }
ClientKeyCredentialsProvider
package com.aliyuncs.kms.auth; import com.aliyuncs.auth.AlibabaCloudCredentials; import com.aliyuncs.auth.AlibabaCloudCredentialsProvider; import com.aliyuncs.auth.KeyPairCredentials; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.exceptions.ServerException; public class ClientKeyCredentialsProvider implements AlibabaCloudCredentialsProvider { private KeyPairCredentials keyPairCredentials; public ClientKeyCredentialsProvider() { } public ClientKeyCredentialsProvider(KeyPairCredentials keyPairCredentials) { this.keyPairCredentials = keyPairCredentials; } @Override public AlibabaCloudCredentials getCredentials() throws ClientException, ServerException { return this.keyPairCredentials; } }