在部署於阿里雲或其他雲環境的公網IP資產中,敏感性資料需要安全儲存與傳輸以降低泄露風險並滿足合規要求。針對體量較小的敏感性資料對象,可直接通過Key Management Service(KMS)線上執行加密與解密操作。本文介紹線上加解密的使用情境、前置條件及具體操作步驟。
適用範圍
單次使用對稱金鑰加解密的資料不超過6 KB。
單次使用非對稱金鑰加解密的資料不超過1KB。
單次加密的資料量越大,網路傳輸失敗可能性越大,網路傳輸所需時間越長,KMS執行個體對資料進行加解密所需時間也越長。
準備工作
在開始調用API進行加解密前,請完成以下準備工作。
步驟一:購買並啟用KMS執行個體
請根據業務需求和安全合規要求,購買並啟用一個KMS執行個體(軟體密鑰管理執行個體和硬體密鑰管理執行個體)。具體操作,請參見購買和啟用KMS執行個體。
步驟二:建立密鑰
根據加密情境,在已啟用的KMS執行個體中建立相應的密鑰。
對稱金鑰:用於在信任環境內進行加解密。
非對稱金鑰:用於跨信任環境的情境,例如用戶端使用公開金鑰加密,服務端使用私密金鑰解密。
具體操作,請參見建立密鑰。
步驟三:準備訪問憑證與許可權
本文以AccessKey方式為例,更多訪問憑證說明,請參見建立訪問憑證。
為確保賬戶安全,切勿使用擁有最高許可權的主帳號AccessKey。應建立並使用具有最小必要許可權的RAM使用者AccessKey進行API訪問。如何建立RAM使用者,請參見建立RAM使用者。
為確保賬戶安全,官方建議建立並使用具有最小必要許可權的RAM使用者AccessKey,而不是使用主帳號的AccessKey進行API訪問。
登入 RAM控制台,建立RAM使用者。
為建立的RAM使用者建立AccessKey。
在 RAM控制台的 使用者頁面,單擊目標RAM使用者名稱稱。
在認證管理 頁簽下的 AccessKey 地區,單擊建立AccessKey,並按照指引完成建立。
重要請妥善保管您的AccessKey ID和Secret。
為RAM使用者授予調用KMS進行加解密的最小許可權。
方式一:設定基於身份的策略
KMS內建了系統權限原則,可以直接綁定到RAM使用者,詳細介紹,請參見Key Management Service系統權限原則參考。
也可以自訂權限原則。以下樣本表示可使用key-hzz65f17868e6cl0n****下,建立的對稱金鑰和非對稱金鑰進行加解密。
{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:AsymmetricEncrypt", "kms:AsymmetricDecrypt" ], "Resource": [ "acs:kms:*:*:key/key-hzz65f17868e6cl0n****" ] } ] }

方式二:設定基於資源的策略
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"));
}
}
}