
# 跨Region容灾加解密
#### 应用场景
当单Region加解密出现服务侧故障时，无法再对数据进行加解密操作，用户可以通过密钥管理服务（Key Management Service，KMS）实现跨Region容灾加解密，保证业务不中断。
#### 解决方案
当一个或多个Region的KMS服务出现故障，只要密钥环中存在一个可用的Region即可完成加解密。
跨Region密钥支持同时使用多个Region的主密钥对一个数据加密，生成唯一的数据密文。解密使用的密钥环，可以使用加密数据时相同的密钥环，也可以使用不同的密钥环，此时解密密钥环只需包含一个或多个加密密钥环中使用的可用的用户主密钥。
![](https://support.huaweicloud.com/bestpractice-dew/public_sys-resources/note_3.0-zh-cn.png)
更多详情请访问：[详情参考](https://github.com/HuaweiCloudDeveloper/huaweicloud-encryption-sdk-java/blob/master-dev/README.md)。
#### 操作流程
![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000001513565997.png "点击放大")
#### 操作步骤
1. 获取AK/SK： 
   - ACCESS_KEY：华为账号Access Key，获取方式请参见[获取AK/SK](https://support.huaweicloud.com/iam_faq/iam_01_0618.html)。
   
   - SECRET_ACCESS_KEY：华为账号Secret Access Key，获取方式请参见[获取AK/SK](https://support.huaweicloud.com/iam_faq/iam_01_0618.html)。
   
   - PROJECT_ID：局点项目ID，获取方式请参见[获取项目ID](https://support.huaweicloud.com/api-iam/iam_17_0002.html)。
   
   - KMS_ENDPOINT：华为云KMS服务访问终端地址，获取方式请参见[终端节点](https://support.huaweicloud.com/api-dew/dew_02_0052.html#section2)。
   
   - 认证用的ak和sk直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中密文存放，使用时解密，确保安全。
   
   - 本示例以ak和sk保存在环境变量中来实现身份验证为例，运行本示例前请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。
   
   
   
   
2. 获取region相关信息。 
   1. [登录DEW服务控制台](https://console.huaweicloud.com/dew/?locale=zh-cn#/dew/)。
   
   2. 鼠标移动至右上方的用户名，在下拉列表中选择"我的凭证"。
   
   3. 获取"项目ID"(PROJECT_ID)和"项目"(REGION)。
      图1获取项目ID和项目   
      ![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000001463091226.png "点击放大") 
   
   4. 单击页面左侧![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000002684474173.png "点击放大")，选择"安全与合规 \> 密码安全中心 DEW"，默认进入"密钥管理"界面。
   
   5. 获取当前Region需要使用的主密钥ID（KEYID）。
      图2获取主密钥ID
      ![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000002361185932.png "点击放大")
      
      
   
   
   
   
3. 使用密钥环加解密。 
   ```
   public class KmsEncryptionExample {
       private static final String ACCESS_KEY = System.getenv("HUAWEICLOUD_SDK_AK");
       private static final String SECRET_ACCESS_KEY = System.getenv("HUAWEICLOUD_SDK_SK");
       private static final String PROJECT_ID_1 = "<projectId1>";
       private static final String REGION_1 = "<region1>";
       private static final String KEYID_1 = "<keyId1>";
       public static final String PROJECT_ID_2 = "<projectId2>";
       public static final String REGION_2 = "<region2>";
       public static final String KEYID_2 = "<keyId2>";
       // 需要加密的数据
       private static final String PLAIN_TEXT = "Hello World!";
       public static void main(String[] args) {
           // 主密钥列表
           List<KMSConfig> kmsConfigList = new ArrayList<>();
           kmsConfigList.add(new KMSConfig(REGION_1, KEYID_1, PROJECT_ID_1));
           kmsConfigList.add(new KMSConfig(REGION_2, KEYID_2, PROJECT_ID_2));
           // 构建加密相关信息
           HuaweiConfig multiConfig = HuaweiConfig.builder().buildSk(SECRET_ACCESS_KEY)
                   .buildAk(ACCESS_KEY)
                   .buildKmsConfig(kmsConfigList)
                   .buildCryptoAlgorithm(CryptoAlgorithm.AES_256_GCM_NOPADDING)
                   .build();
           // 选择密钥环
           KMSKeyring keyring = new KmsKeyringFactory().getKeyring(KeyringTypeEnum.KMS_MULTI_REGION.getType());
           HuaweiCrypto huaweiCrypto = new HuaweiCrypto(multiConfig).withKeyring(keyring);
           // 加密上下文
           Map<String, String> encryptContextMap = new HashMap<>();
           encryptContextMap.put("key", "value");
           encryptContextMap.put("context", "encrypt");
           // 加密
           CryptoResult<byte[]> encryptResult = huaweiCrypto.encrypt(new EncryptRequest(encryptContextMap, PLAIN_TEXT.getBytes(StandardCharsets.UTF_8)));
           // 解密
           CryptoResult<byte[]> decryptResult = huaweiCrypto.decrypt(encryptResult.getResult());
           Assert.assertEquals(PLAIN_TEXT, new String(decryptResult.getResult()));
       }
   }
   ```
   
   
 
