All Products
Search
Document Center

Key Management Service:Examples of using KMS SDK for Java

Last Updated:Jun 15, 2023

This topic provides examples on how to use Key Management Service (KMS) SDK for Java.

Background information

  • You can visit the open source code repository to view sample code of KMS SDK for different programming languages in different scenarios. You are welcome to share your comments or provide your sample code.

  • For more information about API operations of KMS, see List of operations by function.

Preparations

  1. Obtain the dependency declaration of KMS SDK for Java. For more information about the required SDK version, see SDK overview. Example:

    <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>
  2. Obtain the endpoint of KMS based on the region of KMS. For more information, see Make API requests.

    Note
    • If you specify only the region ID of KMS, the public endpoint of KMS for the region is automatically used.

    • If you want to access KMS over a virtual private cloud (VPC), you must specify the VPC address of KMS.

Example 1: Access KMS over a public endpoint or a VPC address

Note

The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using the AccessKey pair to perform operations is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. We recommend that you do not save the AccessKey ID and AccessKey secret in your project code. Otherwise, the AccessKey pair may be leaked and the security of all resources within your account may be compromised.

In this example, the AccessKey pair is saved in ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variables to implement identity authentication. For more information about how to configure authentication information, see Credentials.

  1. Call an encapsulated class to create a KMS client.

    Note

    If the data that you want to encrypt contains special characters <>&, we recommend that you set FormatType to XML to decrypt the data. This helps prevent the errors that occur when the special characters are escaped during decryption. For example, specify 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;
        }
    }
  2. Use the KMS client to call operations, such as the operations to enumerate keys, encrypt data, and decrypt data.

    Note
    • In the following sample code, your Alibaba Cloud account has at least one KMS customer master key (CMK) in the China (Hangzhou) region.

    • The KmsClient.getClientForPublicEndpoint method returns the public endpoint of KMS.

    • The KmsClient.getClientForVpcEndpoint method returns the VPC address of KMS.

    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());
            }
        }
    
     }
                

Example 2: Access Secrets Manager by using a client key-based application access point (AAP)

If you use KMS SDK for Java to access Secrets Manager by using a client key-based AAP, you can use the following sample code.

For more information, see Bind a client key to the 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
    }
}

The preceding sample code references the following code for ClientKeyUtils and 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;
        }
    }