
# 客户端加密简介(Java SDK)
客户端加密是指在传输数据前，使用您选择的加密方法与加密信息，在本地进行数据加密，再将加密后结果发送至OBS服务器，同时将加密方法与解密所需的必要辅助信息存储到对象元数据中。在下载时OBS SDK会依据您提供的密钥与存储在对象元数据中的解密辅助信息进行数据解密，直接返回解密后结果。
![](https://support.huaweicloud.com/sdk-java-devg-obs/public_sys-resources/warning_3.0-zh-cn.png)
- OBS不会以任何方式存储您的主密钥，您必须自行保证主密钥的正确性与完整性，如果主密钥丢失或用错，将会导致您的加密后数据无法解密，OBS不会承担任何责任。
- OBS SDK会将解密所需的必要辅助信息存储在相应对象的元数据中，在对加密对象进行移动、复制、修改元数据等操作时，您需要保证不会修改辅助信息。如果因您删除/修改解密辅助信息而导致数据无法解密，OBS不承担任何责任。
- 出于数据安全原因，未来版本将会从默认的RSA加密方式修改为指定的加密方式（RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING），届时会与旧版本不兼容。
- 建议您在密钥信息（master-key-info）中增加sdk版本信息，以防由于安全问题导致的加密算法、密钥长度限制更改导致的不同sdk版本间的数据加解密失败
- 建议您综合安全和性能方面来决定RSA密钥的长度，未来版本会增加密钥长度限制，必须为3072 bits长度以上。
- 建议您综合安全和性能方面来设置secureRandom。
- 建议您使用pkcs8格式的rsa密钥。
 
#### 加密过程与加密套件
OBS Java SDK提供了两个不同的加密套件生成器，分别是基于AES-CTR加密方法的CTRCipherGenerator与基于RSA + AES-CTR加密的CtrRSACipherGenerator。
使用CTRCipherGenerator上传对象时，用户需要提供一个用来加密数据的数据密钥，SDK将会针对每个对象随机生成一个初始值，并使用数据密钥与初始值加密对象，加密完成后将加密后文件上传至OBS，并将对应的初始值存储至对象元数据中。下载该对象时，用户需要提供对应的数据密钥，SDK会自动获取保存在对象元数据中的初始值，使用数据密钥与初始值解密对象并返回。下载时如果提供了与加密时不同的数据密钥，SDK也将返回不可用的解密后文件。
使用CtrRSACipherGenerator上传对象时，用户需要提供一个RSA 公钥，SDK会针对每个对象随机生成一个数据密钥和初始值，并使用数据密钥与初始值加密对象，加密完成后将加密后文件上传至OBS，随后会使用RSA密钥加密数据密钥，并将加密后的数据密钥与初始值存储至对象元数据中。下载该对象时，用户需要提供对应的RSA私钥，SDK会自动获取保存在对象元数据中的数据密钥与初始值，并使用私钥解密数据密钥，如果提供的私钥与上传时使用的密钥不匹配，将会抛出异常。解密成功后，SDK将会使用解密后的数据密钥与初始值解密对象并返回。
#### 加密客户端与普通客户端的接口变更
CryptoObsClient继承自ObsClient，除下表所列举的接口外，其他接口均与ObsClient保持一致。
表1CryptoObsClient 
| 接口名       | CryptoObsClient接口行为 |
|:---|:---|
| putObject | 将流或文件加密后上传至 OBS     |
| getObject | 返回解密过的数据流           |
   
#### 元数据中的解密信息
SDK会将解密所需的必要信息存至对象的对象自定义元数据，并且不会有其他备份，如果您对这些数据进行了修改，将会造成数据无法解密，需要保存的信息及其含义如下表：
表2 
| **参数名称**                 | **是否必选**       | **描述**                      |
|:---|:---|:---|
| encrypted-algorithm      | 必选             | 加密套件的信息。                    |
| encrypted-object-key     | 必选（使用RSA加密套件时) | 使用RSA密钥加密后的数据密钥。            |
| encrypted-start          | 必选             | 加密该对象所使用的初始值经Base64编码后的字符串。 |
| master-key-info          | 可选             | 加密密钥的信息。                    |
| plaintext-sha256         | 可选             | 加密前对象的sha256，流式上传不计算sha256。 |
| plaintext-content-length | 可选             | 加密前对象的长度，流对象在上传之前无法获取长度。    |
| encrypted-sha256         | 可选             | 加密后对象的sha256，流式上传不计算sha256。 |
   
