
# 使用数据密钥进行本地文件加解密
文件加密，指通过指定算法对文本信息进行加密，使其无法被窃取或修改。
[加密SDK（Encryption SDK）](https://github.com/HuaweiCloudDeveloper/huaweicloud-encryption-sdk-java)是一个客户端密码库，提供了数据的加解密、文件流加解密等功能，旨在帮助客户专注于应用程序的核心功能，而不用关心数据加密和解密的实现过程，用户只需调用加解密接口即可轻松实现海量数据加解密。
![](https://support.huaweicloud.com/bestpractice-dew/public_sys-resources/note_3.0-zh-cn.png)
更多详情请访问：[详情参考](https://github.com/HuaweiCloudDeveloper/huaweicloud-encryption-sdk-java)。
#### 应用场景
对大型文件、图片等数据通过HTTPS请求到KMS服务进行保护时会消耗大量网络资源，降低加密效率。
#### 解决方案
加密SDK通过文件流分段信封加密的原理进行加密。
数据加密通过KMS生成的数据密钥在SDK内部进行，内存中分段加解密文件无需将数据通过网络传输后再进行加解密，保证了文件加密的安全性和正确性。
对于大型文件，SDK执行加密过程中，将文件分段读取到内存中，通过加解密写到目标文件后再进行下一段文件读取和加解密，直至完成整个文件的加解密。
#### 操作流程
![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000001463089378.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_0000002683097495.png "点击放大")，选择"安全与合规 \> 密码安全中心 DEW"，默认进入"密钥管理"界面。
   
   5. 获取当前Region需要使用的主密钥ID（KEYID）。
      图2获取主密钥ID
      ![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000002361185932.png "点击放大")
      
      
   
   6. 获取当前Region需要使用的终端节点（ENDPOINT）。 终端节点（Endpoint）即调用API的**请求地址** ，不同服务不同区域的终端节点不同，您可以从[地区和终端节点](https://developer.huaweicloud.com/endpoint?DEW)中查询服务的终端节点。
      图3获取终端节点   
      ![](https://support.huaweicloud.com/bestpractice-dew/zh-cn_image_0000001478346922.png "点击放大") 
   
   
   
   
3. 文件加解密。 
   ```
   public class KmsEncryptFileExample {
       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 = "<projectId>";
       private static final String REGION = "<region>";
       private static final String KEYID = "<keyId>";
       public static final String ENDPOINT = "<endpoint>";
       public static void main(String[] args) throws IOException {
           // 源文件路径
           String encryptFileInPutPath = args[0];
           // 加密后密文文件路径
           String encryptFileOutPutPath = args[1];
           // 解密后文件路径
           String decryptFileOutPutPath = args[2];
           // 加密上下文
           Map<String, String> encryptContextMap = new HashMap<>();
           encryptContextMap.put("encryption", "context");
           encryptContextMap.put("simple", "test");
           encryptContextMap.put("caching", "encrypt");
           // 构建加密配置
           HuaweiConfig config = HuaweiConfig.builder().buildSk(SECRET_ACCESS_KEY)
                   .buildAk(ACCESS_KEY)
                   .buildKmsConfig(Collections.singletonList(new KMSConfig(REGION, KEYID, PROJECT_ID, ENDPOINT)))
                   .buildCryptoAlgorithm(CryptoAlgorithm.AES_256_GCM_NOPADDING)
                   .build();
           HuaweiCrypto huaweiCrypto = new HuaweiCrypto(config);
           // 设置密钥环
           huaweiCrypto.withKeyring(new KmsKeyringFactory().getKeyring(KeyringTypeEnum.KMS_MULTI_REGION.getType()));
           // 加密文件
           encryptFile(encryptContextMap, huaweiCrypto, encryptFileInPutPath, encryptFileOutPutPath);
           // 解密文件
           decryptFile(huaweiCrypto, encryptFileOutPutPath, decryptFileOutPutPath);
       }
       private static void encryptFile(Map<String, String> encryptContextMap, HuaweiCrypto huaweiCrypto, 
                                       String encryptFileInPutPath, String encryptFileOutPutPath) throws IOException {
           // fileInputStream 加密后文件对应的输入流
           FileInputStream fileInputStream = new FileInputStream(encryptFileInPutPath);
           // fileOutputStream 源文件对应的输出流
           FileOutputStream fileOutputStream = new FileOutputStream(encryptFileOutPutPath);
           // 加密
           huaweiCrypto.encrypt(fileInputStream, fileOutputStream, encryptContextMap);
           fileInputStream.close();
           fileOutputStream.close();
       }
       private static void decryptFile(HuaweiCrypto huaweiCrypto, String decryptFileInPutPath, String decryptFileOutPutPath) throws IOException {
           // in 源文件对应的输入流
           FileInputStream fileInputStream = new FileInputStream(decryptFileInPutPath);
           // out 加密后文件对应的输出流
           FileOutputStream fileOutputStream = new FileOutputStream(decryptFileOutPutPath);
           // 解密
           huaweiCrypto.decrypt(fileInputStream, fileOutputStream);
           fileInputStream.close();
           fileOutputStream.close();
       }
   }
   ```
   
   
 
