在部署于阿里云或其他云环境的公网IP资产中,敏感数据需要安全存储与传输以降低泄露风险并满足合规要求。针对体量较小的敏感数据对象,可直接通过密钥管理服务(KMS)在线执行加密与解密操作。本文介绍在线加解密的使用场景、前置条件及具体操作步骤。
适用范围
单次使用对称密钥加解密的数据不超过6 KB。
单次使用非对称密钥加解密的数据不超过1KB。
单次加密的数据量越大,网络传输失败可能性越大,网络传输所需时间越长,KMS实例对数据进行加解密所需时间也越长。
准备工作
在开始调用API进行加解密前,请完成以下准备工作。
步骤一:购买并启用KMS实例
请根据业务需求和安全合规要求,购买并启用一个KMS实例(软件密钥管理实例和硬件密钥管理实例)。具体操作,请参见购买和启用KMS实例。
步骤二:创建密钥
根据加密场景,在已启用的KMS实例中创建相应的密钥。
对称密钥:用于在信任环境内进行加解密。
非对称密钥:用于跨信任环境的场景,例如客户端使用公钥加密,服务端使用私钥解密。
具体操作,请参见创建密钥。
步骤三:准备访问凭证与权限
本文以AccessKey方式为例,更多访问凭证说明,请参见创建访问凭证。
阿里云账号默认有所有资源的Administrator权限且不可修改,其AccessKey泄露会危及资源安全,因此强烈建议不要为主账号创建AccessKey,请创建专用于API访问的RAM用户并创建对应的AccessKey,并完成最小化授权。具体操作,请参见创建AccessKey。
登录RAM控制台,在用户页面,单击目标RAM用户名称。
在认证管理页签下的AccessKey区域,单击创建AccessKey,并按照指引完成创建。

授予RAM用户访问KMS的权限。
方式一:设置基于身份的策略
KMS内置了系统权限策略,可以直接绑定到RAM用户,详细介绍,请参见密钥管理服务系统权限策略参考。您也可以自定义权限策略。

方式二:设置基于资源的策略
KMS支持基于资源的策略,即为单个密钥和凭据设置访问权限,用于控制哪些阿里云账号、RAM用户、RAM角色有权限来管理或使用KMS密钥、凭据。详细介绍,请参见密钥策略、凭据策略。
步骤四:获取连接信息和CA证书
调用API时,需要根据网络环境选择合适的网关地址(Endpoint)。
本文示例默认使用专属网关。
特性 | 共享网关 | 专属网关 |
Endpoint |
|
|
CA证书 | 无需配置。 | 必须配置。 |
适用场景 | 公网访问、开发测试。 | VPC内网访问、生产环境、更高性能和隔离性。 |
获取方式 | 具体请参见Endpoint。 | 在实例的详情页面,下载实例CA证书,并获取实例VPC地址。 |
应用场景
场景一:应用部署在阿里云上
阿里云上部署的应用服务会产生或收到明文形式的敏感数据,敏感数据需要加密后再通过数据库等方式存储,该场景推荐使用对称加密算法。
相关API
API名称 | 说明 |
使用对称主密钥加密明文 | |
使用对称密钥进行解密。 |
示例代码
加密数据 (Encrypt)
以下示例代码演示了如何调用 Encrypt 接口,使用对称密钥将明文加密成密文。
package com.aliyun.sample;
import com.aliyun.kms20160120.Client;
import com.aliyun.kms20160120.models.EncryptRequest;
import com.aliyun.kms20160120.models.EncryptResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import java.nio.charset.StandardCharsets;
public class SymmetricEncryptSample {
public static Client createClient() throws Exception {
// 使用环境变量中获取的AccessKey ID和AccessKey Secret初始化Client。
// 请确保代码运行环境已设置环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
Config config = new Config()
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
// 设置专属网关Endpoint。
config.endpoint = "<Your-KMS-Instance-Endpoint>";
// 设置KMS实例的CA证书内容。
config.ca = "<Your-CA-Certificate-Content>";
return new Client(config);
}
public static void main(String[] args) throws Exception {
Client client = createClient();
// 待加密的明文。
String plaintext = "this is a test message.";
EncryptRequest encryptRequest = new EncryptRequest()
// 设置要使用的对称密钥ID。
.setKeyId("<Your-Symmetric-Key-Id>")
// 设置待加密的明文。Plaintext需为字节数组,SDK会自动进行Base64编码。
.setPlaintext(plaintext.getBytes(StandardCharsets.UTF_8));
try {
// 调用Encrypt接口。
EncryptResponse response = client.encryptWithOptions(encryptRequest, new RuntimeOptions());
// 从响应中获取Base64编码的密文。
String ciphertextBlob = response.getBody().getCiphertextBlob();
System.out.println("Plaintext: " + plaintext);
System.out.println("Ciphertext (Base64): " + ciphertextBlob);
} catch (Exception e) {
e.printStackTrace();
}
}
}解密数据 (Decrypt)
以下示例代码演示了如何调用 Decrypt 接口,将密文解密成明文。
package com.aliyun.sample;
import com.aliyun.kms20160120.Client;
import com.aliyun.kms20160120.models.DecryptRequest;
import com.aliyun.kms20160120.models.DecryptResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import java.nio.charset.StandardCharsets;
public class SymmetricDecryptSample {
public static Client createClient() throws Exception {
// Client初始化逻辑同加密示例。
Config config = new Config()
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
config.endpoint = "<Your-KMS-Instance-Endpoint>";
config.ca = "<Your-CA-Certificate-Content>";
return new Client(config);
}
public static void main(String[] args) throws Exception {
Client client = createClient();
// 待解密的密文,必须是来自Encrypt接口返回的Base64编码字符串。
String ciphertextBlob = "<Ciphertext-From-Encryption-Step>";
DecryptRequest decryptRequest = new DecryptRequest()
// 设置待解密的密文。
.setCiphertextBlob(ciphertextBlob);
try {
// 调用Decrypt接口。
DecryptResponse response = client.decryptWithOptions(decryptRequest, new RuntimeOptions());
// 从响应中获取解密后的明文字节数组。
byte[] plaintextBytes = response.getBody().getPlaintext().getBytes();
// 根据业务需要将字节数组转换为字符串。
String plaintext = new String(plaintextBytes, StandardCharsets.UTF_8);
System.out.println("Ciphertext (Base64): " + ciphertextBlob);
System.out.println("Decrypted Plaintext: " + plaintext);
} catch (Exception e) {
e.printStackTrace();
}
}
}场景二:应用部署在阿里云上和阿里云外
推荐使用非对称加密算法,实现云外加密、云上解密的业务场景。
云外应用使用公钥加密数据,并将密文传输至云上应用。
云上应用接收到密文后,调用KMS实例通过私钥完成解密。
相关API
API名称 | 说明 |
使用非对称密钥进行加密。 | |
使用非对称密钥进行解密。 |
示例代码
加密
package com.aliyun.sample;
import com.aliyun.tea.*;
public class Sample {
/**
* <b>description</b> :
* <p>使用凭据初始化账号Client</p>
* @return Client
*
* @throws Exception
*/
public static com.aliyun.kms20160120.Client createClient() throws Exception {
// 工程代码建议使用更安全的无AK方式,凭据配置方式请参见:https://www.alibabacloud.com/help/document_detail/378657.html。
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
config.endpoint = "kst-hzz65f176a0ogplgq****.cryptoservice.kms.aliyuncs.com";
//KMS实例CA证书
config.ca = "-----BEGIN CERTIFICATE-----MIIDuzCCAqOgAwIBAgIJALTKwWAjvbMiMA0GCS****";
return new com.aliyun.kms20160120.Client(config);
}
public static void main(String[] args) throws Exception {
com.aliyun.kms20160120.Client client = Sample.createClient();
com.aliyun.kms20160120.models.AsymmetricEncryptRequest asymmetricEncryptRequest = new com.aliyun.kms20160120.models.AsymmetricEncryptRequest()
.setPlaintext("test")
.setKeyId("a06e2410-*****-330777ee1825")
.setKeyVersionId("key-hzz65f17868e6cl0n****")
.setAlgorithm("RSAES_OAEP_SHA_256");
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
try {
com.aliyun.kms20160120.models.AsymmetricEncryptResponse resp = client.asymmetricEncryptWithOptions(asymmetricEncryptRequest, runtime);
System.out.println(new com.google.gson.Gson().toJson(resp));
} catch (TeaException error) {
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
System.out.println(error.getMessage());
// 诊断地址
System.out.println(error.getData().get("Recommend"));
} catch (Exception _error) {
TeaException error = new TeaException(_error.getMessage(), _error);
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
System.out.println(error.getMessage());
// 诊断地址
System.out.println(error.getData().get("Recommend"));
}
}
}解密
public class Sample {
/**
* <b>description</b> :
* <p>使用凭据初始化账号Client</p>
* @return Client
*
* @throws Exception
*/
public static com.aliyun.kms20160120.Client createClient() throws Exception {
// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
// 专属网关Endpoint
config.endpoint = "kst-hzz65f176a0ogplgq****.cryptoservice.kms.aliyuncs.com";
//KMS实例CA证书
config.ca = "-----BEGIN CERTIFICATE-----MIIDuzCCAqOgAwIBAgIJALTKwWAjvbMiMA0GCS****";
return new com.aliyun.kms20160120.Client(config);
}
public static void main(String[] args_) throws Exception {
public static void main(String[] args_) throws Exception {
com.aliyun.kms20160120.Client client = Sample.createClient();
com.aliyun.kms20160120.models.AsymmetricDecryptRequest asymmetricDecryptRequest = new com.aliyun.kms20160120.models.AsymmetricDecryptRequest()
.setKeyId("a06e2410-*****-330777ee1825")
.setKeyVersionId("key-hzz65f17868e6cl0n****")
.setAlgorithm("RSAES_OAEP_SHA_256")
.setCiphertextBlob("FV9i23PQdpGPvc*********MA==");
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
try {
com.aliyun.kms20160120.models.AsymmetricDecryptResponse resp = client.asymmetricDecryptWithOptions(asymmetricDecryptRequest, runtime);
System.out.println(new com.google.gson.Gson().toJson(resp));
} catch (TeaException error) {
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
System.out.println(error.getMessage());
// 诊断地址
System.out.println(error.getData().get("Recommend"));
} catch (Exception _error) {
TeaException error = new TeaException(_error.getMessage(), _error);
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
System.out.println(error.getMessage());
// 诊断地址
System.out.println(error.getData().get("Recommend"));
}
}
}