
# RSA非对称数据加解密
当您需要进行传递敏感信息时（例如密钥的交换），需要对敏感数据进行加密，使用非对称密钥加解密的方案从信息接收者的角度来说，您需要进行以下操作：
1. 创建非对称加密密钥，算法选择"RSA_3072"，详情请参见[创建密钥](https://support.huaweicloud.com/api-dew/CreateKey.html)。
2. 获取公钥，详情请参见[查询公钥信息](https://support.huaweicloud.com/api-dew/ShowPublicKey.html)。
3. 信息接收者将公钥分发给信息发送者。
4. 信息发送者用得到的公钥对敏感数据进行本地加密后，将密文发送给信息接收者。
5. 信息接收者拿到密文后，调用 KMS 的解密功能对密文解，详情请参见[解密数据](https://support.huaweicloud.com/api-dew/DecryptData.html)。
在整个敏感数据的传输的过程中，使用密文进行传输，而唯一能解密该密文的密钥托管在密钥管理系统 KMS 中保护，任何人都无法获取到您的密钥，极大程度上提高了敏感数据加密传输安全性。
#### 操作示例
本文提供如下示例：
使用RSA_3072主密钥，密钥用途为ENCRYPT_DECRYPT。使用公钥离线加密"hello world!"，调用decrypt-data使用私钥进行解密，加解密使用的算法为"RSA/ECB/OAEPWithSHA-256AndMGF1Padding"：
```
public class RsaEncryptDataExample {
    /**
     * 基础认证信息：
     * - ACCESS_KEY: 华为云账号Access Key，获取方式请参见获取AK/SK。
     * - SECRET_ACCESS_KEY: 华为云账号Secret Access Key, 敏感信息，建议密文存储，获取方式请参见获取AK/SK。
     * - IAM_ENDPOINT: 华为云IAM服务访问终端地址，获取方式请参见IAM终端节点。
     * - KMS_REGION_ID: 华为云KMS支持的地域,，获取方式请参见地区和终端节点。
     * - KMS_ENDPOINT: 华为云KMS服务访问终端地址，获取方式请参见终端节点。
     * - 认证用的ak和sk直接写到代码中有很大的安全风险，建议在配置文件或者环境变量中密文存放，使用时解密，确保安全。
     * - 本示例以ak和sk保存在环境变量中来实现身份验证为例，运行本示例前请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。
     */
    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 IAM_ENDPOINT = "https://<IamEndpoint>";
    private static final String KMS_REGION_ID = "<RegionId>";
    private static final String KMS_ENDPOINT = "https://<KmsEndpoint>";
    private static final String RSA_PUBLIC_KEY_BEGIN = "-----BEGIN PUBLIC KEY-----\n";
    private static final String RSA_PUBLIC_KEY_END = "-----END PUBLIC KEY-----";
    private static final String RSAES_OAEP_SHA_256 = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
    private static final String SHA_256 = "SHA-256";
    private static final String MGF1 = "MGF1";
    private static final String HELLO_WORLD = "hello world!";
    public static void main(String[] args) throws Exception {
        final String keyId = args[0];
        publicKeyEncrypt(keyId);
    }
    private static void publicKeyEncrypt(String keyId) throws NoSuchAlgorithmException, InvalidKeySpecException,
            NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException,
            IllegalBlockSizeException, BadPaddingException {
        // 1.准备访问华为云的认证信息
        final BasicCredentials auth = new BasicCredentials()
                .withIamEndpoint(IAM_ENDPOINT).withAk(ACCESS_KEY).withSk(SECRET_ACCESS_KEY);
        // 2.初始化SDK，传入认证信息及KMS访问终端地址
        final KmsClient kmsClient = KmsClient.newBuilder()
                .withRegion(new Region(KMS_REGION_ID, KMS_ENDPOINT)).withHttpConfig(new HttpConfig()
                        .withIgnoreSSLVerification(true)).withCredential(auth).build();
        // 3.获取公钥信息,返回的是PKCS8格式
        final ShowPublicKeyRequest showPublicKeyRequest = new ShowPublicKeyRequest()
                .withBody(new OperateKeyRequestBody().withKeyId(keyId));
        final ShowPublicKeyResponse showPublicKeyResponse = kmsClient.showPublicKey(showPublicKeyRequest);
        // 4.获取公钥字符串
        final String publicKeyStr = showPublicKeyResponse.getPublicKey().replace(RSA_PUBLIC_KEY_BEGIN, "")
                .replaceAll("\n", "").replace(RSA_PUBLIC_KEY_END, "");
        // 5.获取公钥二进制
        final X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr));
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA", new BouncyCastleProvider());
        final PublicKey publicKey = keyFactory.generatePublic(keySpec);
        // 6.公钥离线加密字符串"hello world!"
        final Cipher cipher = Cipher.getInstance(RSAES_OAEP_SHA_256);
        final OAEPParameterSpec oaepParameterSpec = new OAEPParameterSpec(SHA_256, MGF1,
                new MGF1ParameterSpec(SHA_256), PSource.PSpecified.DEFAULT);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParameterSpec);
        final byte[] cipherData = cipher.doFinal(HELLO_WORLD.getBytes(StandardCharsets.UTF_8));
        // 7.私钥在线解密
        final DecryptDataRequest decryptDataRequest = new DecryptDataRequest()
                .withBody(new DecryptDataRequestBody().withKeyId(keyId)
                        .withEncryptionAlgorithm(DecryptDataRequestBody.EncryptionAlgorithmEnum.RSAES_OAEP_SHA_256)
                        .withCipherText(Base64.getEncoder().encodeToString(cipherData)));
        final DecryptDataResponse decryptDataResponse = kmsClient.decryptData(decryptDataRequest);
        assert HELLO_WORLD.equals(decryptDataResponse.getPlainText());
    }
}
```
