编辑代码

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;

/**
 * @Author hqf
 * @Description //加解密标准流程
 * @Date  2021/11/11 11:33
 * @Param
 * @return
 **/
public class LXRSAUtils {
    private static final String KEY_ALGORITHM = "RSA";

    private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";

    private static final int MAX_ENCRYPT_BLOCK = 117;

    private static final int MAX_DECRYPT_BLOCK = 128;



    /**
     * 生成秘钥对
     * @return
     * @throws Exception
     */
    public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }

    /**
     * 获取公钥(Base64编码)
     * @param keyPair
     * @return
     */
    public static String getPublicKey(KeyPair keyPair){
        PublicKey publicKey = keyPair.getPublic();
        byte[] bytes = publicKey.getEncoded();
        return byte2Base64(bytes);
    }

    /**
     * 获取私钥(Base64编码)
     * @param keyPair
     * @return
     */
    public static String getPrivateKey(KeyPair keyPair){
        PrivateKey privateKey = keyPair.getPrivate();
        byte[] bytes = privateKey.getEncoded();
        return byte2Base64(bytes);
    }

    /**
     * 将Base64编码后的公钥转换成PublicKey对象
     * @param pubStr
     * @return
     * @throws Exception
     */
    public static PublicKey string2PublicKey(String pubStr) throws Exception{
        byte[] keyBytes = base642Byte(pubStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    /**
     * 将Base64编码后的私钥转换成PrivateKey对象
     * @param priStr
     * @return
     * @throws Exception
     */
    public static PrivateKey string2PrivateKey(String priStr) throws Exception{
        byte[] keyBytes = base642Byte(priStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /**
     * 字节数组转Base64编码
     * @param bytes
     * @return
     */
    public static String byte2Base64(byte[] bytes){
        return java.util.Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * Base64编码转字节数组
     * @param base64Key
     * @return
     */
    public static byte[] base642Byte(String base64Key) {
        return java.util.Base64.getDecoder().decode(base64Key);
    }


    /**
     * 公钥加密
     *
     * @param data      源数据ey 公钥(BASE64编码)
     * @param publicKey
     */
    public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
        byte[] keyBytes = Base64.decodeBase64(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }

    /**
     * 公钥加密
     *
     * @param data      源数据ey 公钥(BASE64编码)
     * @param publicKey
     */
    public static String encryptByPublicKey(String data, String publicKey) throws Exception {
        byte[] dataBytes = data.getBytes("utf-8");
        byte[] keyBytes = Base64.decodeBase64(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(dataBytes, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        String enResult = Base64.encodeBase64String(encryptedData);
        return enResult;
    }

    /**
     * 私钥解密
     *
     * @param encryptedData 已加密数据
     * @param privateKey    私钥(BASE64编码)
     */
    public static String decryptByPrivateKey(String encryptedData, String privateKey) throws Exception {
        byte[] decodeBytes = Base64.decodeBase64(encryptedData);
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        int inputLen = decodeBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(decodeBytes, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(decodeBytes, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        String decryptInfo = new String(decryptedData, "utf-8");
        return decryptInfo;
    }


    /**
     * 私钥解密
     *
     * @param encryptedData 已加密数据
     * @param privateKey    私钥(BASE64编码)
     */
    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;
    }

    /**
     * 用私钥对信息生成数字签名
     *
     * @param data       已加密数据
     * @param privateKey 私钥(BASE64编码)
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
        byte[] keyBytes = Base64.decodeBase64(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateK);
        signature.update(data);
        return Base64.encodeBase64String(signature.sign());
    }

    /**
     * 用私钥对信息生成数字签名
     *
     * @param data       已加密数据
     * @param privateKey 私钥(BASE64编码)
     */
    public static String sign(String data, String privateKey) throws Exception {
        byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
        return sign(dataBytes, privateKey);
    }

    /**
     * 校验数字签名
     *
     * @param data
     * @param publicKey
     * @param sign
     */
    public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
        byte[] keyBytes = Base64.decodeBase64(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicK);
        signature.update(data);
        return signature.verify(Base64.decodeBase64(sign));
    }

    /**
     * 校验数字签名
     *
     * @param data
     * @param publicKey
     * @param sign
     */
    public static boolean verify(String data, String publicKey, String sign) throws Exception {
        byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
        return verify(dataBytes, publicKey, sign);
    }

    /**
     * 公私钥生成
     *
     */
    public static void initRsa() throws Exception {
        //===============生成公钥和私钥,公钥传给客户端,私钥服务端保留==================
        //生成RSA公钥和私钥,并Base64编码,生成一次以后,就写死在配置文件或代码中,下次不再重新生成
        KeyPair keyPair = getKeyPair();
        String publicKeyStr = getPublicKey(keyPair);
        String privateKeyStr = getPrivateKey(keyPair);
        System.out.println("RSA公钥Base64编码:" + publicKeyStr);
        System.out.println("RSA私钥Base64编码:" + privateKeyStr);

    }

    public static void main(String[] args) throws Exception {

        //1 公私钥生成
        String wkPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCe11v/ZN1dMP0ehXnw5LQhDKVKB0yE4JKcYvmr+mrao/0P+HXFIeQ4bJjXFIa/BtwJg89CCFxpIT1TSKxGs2b5HK4tNnHpn6UYYrOC/lwfmE7G56qOyxpK8QsWSI8j/U5JLFCPf2Iv3CW4OGSP6BG1KAjOugWqFHi5vX104VDXmwIDAQAB";
        String wkPrivateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJ7XW/9k3V0w/R6FefDktCEMpUoHTITgkpxi+av6atqj/Q/4dcUh5DhsmNcUhr8G3AmDz0IIXGkhPVNIrEazZvkcri02cemfpRhis4L+XB+YTsbnqo7LGkrxCxZIjyP9TkksUI9/Yi/cJbg4ZI/oEbUoCM66BaoUeLm9fXThUNebAgMBAAECgYBB7T7Y3MNoB4o3Xc0D59i/kuETvb3LtO4FDKt17uTkxIWnWEeBP5TaunAhbPqUVMOFC3k9ffzlAY/TfmlKmvGUsKBHTJA6YETvtp3bqGyeb4xU6J6/YDIy45ca3MJ+ZLkc7LFVp6ZRHWPKaxCoA2dCbMjOFHEv3EkF3Gq9fA+riQJBAObKROYkB5RWogPSHzWD/klZ/7Nxakld+/2dXMeDK355Ea9tAaYxev8u5NDiRGYo8e0PdPVSo4MAIVdCaK439ucCQQCwMSNmaoXCscgABHHaGil1Bw0CShod+oH2d/NZErecb7oyCZUV/2llTushwp8K6whKe1x8ZfZNBd5lt37q0OctAkB40s/7REWLjUdIhMq985o+wJUzVl70hfWUsruN38f3cF6n3oOMhD8GNYCpMqvoZ+sv1nW+sULVJE5QJn4zJy1lAkA7ycDofRc81RU4JEn6J8yPoL/iWgD40UwOte+G91oFJMi7OBM2LsC2FwylHSTZEJ50n93nfLYStv4b6COSTSdVAkEApgf/0at6okMkIpLgzXla9W+L4z8dX/L2AUIJ9NNyXHSvrMACnaj6O4QZ35kvm8Hm0usmbmaW9r3Pzd38x1F6LQ==";

        //2.16位随机秘钥,用来生成AES,对应需要平台方生成;
        String key = "kYQyymtMSjbiPV5o";

        HashMap<String, Object> param = new HashMap<>();
        JSONObject bizData = new JSONObject();
        bizData.put("mobile","17600518484");
        bizData.put("certId","141124199204090078");
        bizData.put("name","张三");
        param.put("channelId","105900001");//渠道号:资金方分配给平台
        param.put("timestamp",System.currentTimeMillis());
        param.put("bizData",bizData);//请求实体
        System.out.println("【请求明文】"+JSON.toJSONString(param));
        //5.AES加密请求实体bizData
        String encrypt = LXAESUtil.encrypt(JSON.toJSONString(bizData), key);
        param.put("bizData",encrypt);
        System.out.println("【AES加密后密文bizData】"+encrypt);
        String data = JSON.toJSONString(param, SerializerFeature.SortField,
                SerializerFeature.MapSortField,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteNullStringAsEmpty,
                SerializerFeature.WriteNullListAsEmpty);
        //3 获取签名
        String sign = sign(data,wkPrivateKey);
        //4.请求参数需要带上sign
        System.out.println("【签名sign】"+sign);
        param.put("sign",sign);

        //6.接口调用
        System.out.println("【接口调用入参】"+JSON.toJSONString(param));
        System.out.println("============================================省略接口调用================================================================");

        //解密流程:

        System.out.println("==================================解密流程开始========================================================");

        //1.验证签名 需要在data中去除sign字段
        param.remove("sign",sign);
        String result = JSON.toJSONString(param);
        boolean verify = verify(result,wkPublicKey,sign);
        System.out.println("【验签结果】"+verify);
        if(verify){
            //2.验签通过,进行解密AES解密
            String decrypt = LXAESUtil.decrypt(encrypt, key);
            System.out.println("AES解密后内容:"+decrypt);
            //3.解密后报文
            JSONObject jsonObject = JSONObject.parseObject(decrypt);
            param.put("bizData", jsonObject);
            System.out.println("【解密后报文】"+JSON.toJSONString(param));
        }

    }
}