阿里云KMS 的信封加密

信封加密是一种数据安全传输方式,通过将数据装入加密信封,使用单独的加密密钥存储,确保即使获取到数据也无法解密。其流程涉及检查并分离密钥与加密数据。
摘要由CSDN通过智能技术生成

信封加密

何为信封加密,大概意思就是一批数据可以装在一个信封里进行安全传输,何为安全传输,就是加密密钥和加密的数据是分开存储的,获取任何一个都无法进行解密操作。

流程如下:
在这里插入图片描述

  1. 信封加密实例版本参考如下:
package com.qdum.smsservice.config;

import com.aliyun.dkms.gcs.openapi.models.Config;
import com.aliyun.dkms.gcs.sdk.Client;
import com.aliyun.dkms.gcs.sdk.models.*;
import com.aliyun.tea.TeaException;
import com.qdum.smsservice.common.model.BaseDto;
import com.qdum.smsservice.domain.AdvanceGenerateDataKeyInfo;
import com.qdum.smsservice.web.rest.errors.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileNotFoundException;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Mr.sunql
 * @description
 *   kms 实例版本
 * @date Created in15:34 2024/8/19
 */
public class KmsAdvanceClient {

    private static final Logger log = LoggerFactory.getLogger(KmsAdvanceClient.class);

    private static String endpoint = "kst-8988888888.cryptoservice.kms.aliyuncs.com";
    private static String clientKeyPass = "af6fe64e58553b4599c965653a090b47";
    private static Client client;
    private static final int GCM_IV_LENGTH = 12;
    private static final int GCM_TAG_LENGTH = 16;
    private static final String iv_base64 = "KYJOxtYbd3Rmn5zB";


    /**
     * 初始化client 链接
     * @return
     */
    public static Client getKmsClient(){
        String clientKeyFilePath = null;
        String cafilePath=null;
        try {
            clientKeyFilePath = ResourceUtils.getFile("classpath:kms/clientKey.json").getPath();
            cafilePath=ResourceUtils.getFile("classpath:kms/ca.pem").getPath();
            client = new Client(new Config()
                .setProtocol("https")
                .setEndpoint(endpoint)
                .setCaFilePath(cafilePath) // 设置CA证书文件路径,还支持设置CA证书内容,请根据需要选择。
                .setClientKeyFile(clientKeyFilePath)//设置应用身份凭证文件路径,还支持设置应用身份凭证内容,请根据需要选择。
                .setPassword(clientKeyPass));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }catch (Exception e) {
            e.printStackTrace();
        }
        log.info("获取连接 kmsClient=>{}",client);
        return client;
    }

    /**
     * 生成密钥
     * @param keyId
     * @return
     */
    public static AdvanceGenerateDataKeyInfo advanceGenerateData(String keyId){
        Client kmsClient = KmsAdvanceClient.getKmsClient();
        AdvanceGenerateDataKeyRequest advanceGenerateDataKeyRequest=new AdvanceGenerateDataKeyRequest();
        advanceGenerateDataKeyRequest.setKeyId(keyId);
        advanceGenerateDataKeyRequest.setNumberOfBytes(32);
        AdvanceGenerateDataKeyResponse advanceGenerateDataKeyResponse=null;
        AdvanceGenerateDataKeyInfo advanceGenerateDataKeyInfo=new AdvanceGenerateDataKeyInfo();
        try {
            advanceGenerateDataKeyResponse = kmsClient.advanceGenerateDataKey(advanceGenerateDataKeyRequest);
            log.info("KeyId:{} ,Plaintext:{} ,CiphertextBlob: {} ,Iv: {}",advanceGenerateDataKeyResponse.getKeyId(),advanceGenerateDataKeyResponse.getPlaintext(),Arrays.toString(advanceGenerateDataKeyResponse.getCiphertextBlob()),Arrays.toString(advanceGenerateDataKeyResponse.getIv()));
            advanceGenerateDataKeyInfo.setIv(Base64.getEncoder().withoutPadding().encodeToString(advanceGenerateDataKeyResponse.getIv()));
            advanceGenerateDataKeyInfo.setAlgorithm(advanceGenerateDataKeyResponse.getAlgorithm());
            advanceGenerateDataKeyInfo.setKeyVersionId(advanceGenerateDataKeyResponse.getKeyVersionId());
            advanceGenerateDataKeyInfo.setCiphertextBlob(Base64.getEncoder().withoutPadding().encodeToString(advanceGenerateDataKeyResponse.ciphertextBlob));
            advanceGenerateDataKeyInfo.setRequestId(advanceGenerateDataKeyResponse.getRequestId());
            advanceGenerateDataKeyInfo.setKeyId(advanceGenerateDataKeyResponse.getKeyId());
            advanceGenerateDataKeyInfo.setPlaintext(Base64.getEncoder().withoutPadding().encodeToString(advanceGenerateDataKeyResponse.plaintext));
        } catch (TeaException e) {
            log.error("code: {} ,message: {},requestId:{}", ((TeaException) e).getCode(),e.getMessage(),((TeaException) e).getData().get("requestId"));
            e.printStackTrace();
        } catch (Exception e) {
            log.error("advanceGenerateData err:{}", e.getMessage());
            e.printStackTrace();
        }
        return advanceGenerateDataKeyInfo;
    }


    /**
     * 信封加密
     * @param plaintext 待加密的明文
     * @param base64PlainDataKey 明文密钥
     * @return
     */
    public static String advanceEncrypt(String plaintext,String base64PlainDataKey) {
        byte[] data = plaintext.getBytes(StandardCharsets.UTF_8);
        byte[] iv = null; // 加密初始向量,解密时也需要传入
        byte[] cipherText = null; // 密文
        try {
            iv = new byte[GCM_IV_LENGTH];
            SecureRandom random = new SecureRandom();
            random.nextBytes(iv);
            iv = Base64.getDecoder().decode(iv_base64);
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(base64PlainDataKey), "AES");
            GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec);
            cipherText = cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
       return Base64.getEncoder().withoutPadding().encodeToString(cipherText);
    }


    /**
     * 解密数据
     * @param keyId
     * @param base64DataKeyIv  初始向量
     * @param base64EncryptedDataKey 密钥密文
     * @param base64CipherText base64加密内容
     * @return
     */
    public static String advanceDecrypt(String keyId,String base64DataKeyIv, String base64EncryptedDataKey,String base64CipherText) {
        Client kmsClient = KmsAdvanceClient.getKmsClient();
        byte[] plainDataKey = null;
        byte[] decryptedData=null;
        try {
            DecryptRequest decryptRequest = new DecryptRequest()
                .setKeyId(keyId)
                .setCiphertextBlob(Base64.getDecoder().decode(base64EncryptedDataKey))
                .setIv(Base64.getDecoder().decode(base64DataKeyIv));
            DecryptResponse decryptResponse = kmsClient.decrypt(decryptRequest);
            //先获取数据密钥的明文
            plainDataKey = decryptResponse.getPlaintext();
            //再进行本地解密数据
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            SecretKeySpec keySpec = new SecretKeySpec(plainDataKey, "AES");
            GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, Base64.getDecoder().decode(iv_base64));
            cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
            decryptedData = cipher.doFinal(Base64.getDecoder().decode(base64CipherText));
        } catch (TeaException e) {
            log.info("code: {} ,message: {} ,requestId: {}", ((TeaException) e).getCode(), e.getMessage(), ((TeaException) e).getData().get("requestId"));
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (Exception e) {
            log.info("advanceDecrypt err: {}", e.getMessage());
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return new String(decryptedData, StandardCharsets.UTF_8);
    }



}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵豸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值