RSA算法实现数据加密签名传输与数据解密代码实例(上)

1. RSA算法实现数据加解密与签名的原理浅析:RSA算法实现数据的加解密与签名都是通过一对非对称的密钥对(公钥与私钥)来实现的,公钥可对外公开给其他要传输数据给我的人使用,私钥留着我自己对加密的数据进行解密时使用。公钥通常用来加密数据,私钥通常用来解密数据。使用私钥签名主要是为了防止传送的数据被篡改。

2. 废话不多说,直接上代码

 项目目录结构:

 

 

 

RSA密钥常量文件

package com.sxy.rsademo.rsa;

/**
 * @Description 密钥相关常量
 * @By SuXingYong
 * @DateTime 2020/7/11 23:35
 **/
public class KeyConstant {

    /** 字符编码  **/
    public final static String CHARACTER_ENCODING_FORMAT = "utf-8";

    /** 密钥常量 -  密钥采用的算法 **/
    public final static String KEY_ALGORITHM = "RSA";

    /** 密钥常量 -  签名算法 **/
    public final static String SIGN_ALGORITHMS = "MD5withRSA";

    /**
     * 密钥长度,DH算法的默认密钥长度是1024
     * 密钥长度必须是64的倍数,在512到65536位之间
     **/
    public final static int KEY_SIZE = 1024;

    /** 最大 - 加密字节数组 - 大小 **/
    public final static int ENCRYPT_MAX_SIZE = 117;

    /** 最大 - 解密字节数组 - 大小 **/
    public final static int DECRYPT_MAX_SIZE = 128;

    /** RSA - 模式 - 01 - 加密 **/
    public final static String RSA_MODE_01 = "encrypt";

    /** RSA - 模式 - 02 - 解密 **/
    public final static String RSA_MODE_02 = "decrypt";

    /** 公钥 **/
    public final static String PUBLIC_KEY = "public.key";

    /** 私钥 **/
    public final static String PRIVATE_KEY = "private.key";

    /** A方 - 原文 **/
    public final static String A_ORIGINAL_TEXT = "aOriginalText";

    /** B方 - 原文 **/
    public final static String B_ORIGINAL_TEXT = "bOriginalText";

    /** A方 - 公钥 - 密文 **/
    public final static String  A_PUBLIC_KEY_CIPHER_TEXT = "aPublicKeyCipherText";

    /** A方 - 私钥 - 密文 **/
    public final static String A_PRIVATE_KEY_CIPHER_TEXT = "aPrivateKeyCipherText";

    /** A方 - 公钥 - 明文 **/
    public final static String A_PUBLIC_KEY_PLAIN_TEXT = "aPublicKeyPlainText";

    /** A方 - 私钥 - 明文 **/
    public final static String A_PRIVATE_KEY_PLAIN_TEXT = "aPrivateKeyPlainText";

    /** B方 - 公钥 - 密文 **/
    public final static String  B_PUBLIC_KEY_CIPHER_TEXT = "bPublicKeyCipherText";

    /** B方 - 私钥 - 密文 **/
    public final static String B_PRIVATE_KEY_CIPHER_TEXT = "bPrivateKeyCipherText";

    /** B方 - 公钥 - 明文 **/
    public final static String B_PUBLIC_KEY_PLAIN_TEXT = "bPublicKeyPlainText";

    /** B方 - 私钥 - 明文 **/
    public final static String B_PRIVATE_KEY_PLAIN_TEXT = "bPrivateKeyPlainText";

    /** A方 - 私钥 - 签名 - 原文 **/
    public final static String A_PRIVATE_KEY_SIGN_ORIGINAL_TEXT = "aPrivateKeySignOriginalText";

    /** A方 - 私钥 - 签名 - 密文 **/
    public final static String A_PRIVATE_KEY_SIGN_CIPHER_TEXT = "aPrivateKeySignCipherText";

    /** B方 - 私钥 - 签名 - 原文 **/
    public final static String B_PRIVATE_KEY_SIGN_ORIGINAL_TEXT = "bPrivateKeySignOriginalText";

    /** B方 - 私钥 - 签名 - 密文 **/
    public final static String B_PRIVATE_KEY_SIGN_CIPHER_TEXT = "bPrivateKeySignCipherText";

    /** 私钥 - 签名 - 合法性 **/
    public final static String PRIVATE_KEY_SIGN_VERIFY = "privateKeySignVerify";

    /** 公钥文件存储路径 **/
    public final static String PUBLIC_KEY_FILE_ULR = "d:/upload/rsaKey/publicKey.keystore";

    /** 私钥钥文件存储路径 **/
    public final static String PRIVATE_KEY_FILE_ULR = "d:/upload/rsaKey/privateKey.keystore";

    /** 密钥名称和值的分隔符 **/
    public final static String KEY_AND_VALUE_SEPARATOR = "==>";

    /** 公钥文件存储路径 -  键名 **/
    public final static String PUBLIC_KEY_FILE_SAVE_PATH = "publicKeyFile.savePath";

    /** 私钥钥文件存储路径 -  键名 **/
    public final static String PRIVATE_KEY_FILE_SAVE_PATH = "privateKeyFile.savePath";


}
KeyConstant.java

RSA工具类:

package com.sxy.rsademo.rsa;

import com.sxy.rsademo.utils.Base64;
import com.sxy.rsademo.utils.CastUtils;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Description: RSA 工具类
 * @Author: SuXingYong
 * @Date 2020/7/11 23:35
 **/
@Slf4j
public class RsaUtils extends KeyConstant {

    /************************************************* 密钥初始化、持久化、获取start  *************************************************/

    /**
     * @Description 初始化密钥对
     *                返回甲方密钥的Map
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param []
     * @Return java.util.Map<java.lang.String,java.lang.Object>
     **/
    public static Map<String,Object> initKey(){
        // 将密钥存储在map中
        Map<String,Object> keyMap = new HashMap<String,Object>();
        try {
            // 实例化密钥生成器 采用RSA算法
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            // 初始化密钥生成器 1024
            keyPairGenerator.initialize(KEY_SIZE);
            // 生成密钥对
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            // 甲方公钥
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            log.info("系数:"+publicKey.getModulus()+"  加密指数:"+publicKey.getPublicExponent());
            // 甲方私钥
            RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();
            log.info("系数:"+privateKey.getModulus()+"  解密指数:"+privateKey.getPrivateExponent());

            // 公钥
            keyMap.put(PUBLIC_KEY, Base64.encode(publicKey.getEncoded()));
            // 私钥
            keyMap.put(PRIVATE_KEY,  Base64.encode(privateKey.getEncoded()));
            // 公钥持久性文件存储地址
            String publicKeyFileSavePath = PUBLIC_KEY_FILE_ULR;
            if (publicKeyFileSavePath != null && !publicKeyFileSavePath.equals("")){
                keyMap.put(PUBLIC_KEY_FILE_SAVE_PATH,publicKeyFileSavePath);
            }
            // 私钥持久性文件存储地址
            String privateKeyFileSavePath = PRIVATE_KEY_FILE_ULR;
            if (privateKeyFileSavePath != null && !privateKeyFileSavePath.equals("")){
                keyMap.put(PRIVATE_KEY_FILE_SAVE_PATH,privateKeyFileSavePath);
            }
            // 密钥对持久化存储
            RsaUtils.saveKeyPairToFile(keyMap);
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return keyMap;
    }


    /**
     * @Description 保存密钥对 到文件中
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [keyMap]
     * @Return void
     **/
    public static void saveKeyPairToFile(Map<String,Object> keyMap){
        try {
            // 公钥原始字符串
            String publicKeyOriginalString = CastUtils.castString(keyMap.get(PUBLIC_KEY));
            log.info("公钥:"+publicKeyOriginalString);
            // 私钥原始字符串
            String privateKeyOriginalString = CastUtils.castString(keyMap.get(PRIVATE_KEY));
            log.info("私钥:"+privateKeyOriginalString);
            // 需要存储的公钥字符串键值对
            StringBuilder publicKeyOutString = new StringBuilder("");
            publicKeyOutString.append(PUBLIC_KEY).append(KEY_AND_VALUE_SEPARATOR).append(publicKeyOriginalString);
            // 需要存储的私钥字符串键值对
            StringBuilder privateKeyOutString = new StringBuilder("");
            privateKeyOutString.append(PUBLIC_KEY).append(KEY_AND_VALUE_SEPARATOR).append(privateKeyOriginalString);
            // 公钥存储地址
            String publicKeyPath = CastUtils.castString(keyMap.get(PUBLIC_KEY_FILE_SAVE_PATH));
            File publicKeyFile = new File(publicKeyPath);
            if (!publicKeyFile.exists()){
                publicKeyFile.getParentFile().mkdirs();
            }
            log.info("公钥存储地址:"+publicKeyPath);
            // 私钥存储地址
            String privateKeyPath = CastUtils.castString(keyMap.get(PRIVATE_KEY_FILE_SAVE_PATH));
            File privateKeyFile = new File(privateKeyPath);
            if (!privateKeyFile.exists()){
                privateKeyFile.getParentFile().mkdirs();
            }
            log.info("私钥存储地址:"+privateKeyPath);
            // 将密钥对写入到文件
            FileWriter publicFileWriter = new FileWriter(publicKeyPath);
            FileWriter privateFileWriter = new FileWriter(privateKeyPath);
            BufferedWriter publicBufferedWriter = new BufferedWriter(publicFileWriter);
            BufferedWriter privateBufferedWriter = new BufferedWriter(privateFileWriter);
            publicBufferedWriter.write(publicKeyOutString.toString());
            privateBufferedWriter.write(privateKeyOutString.toString());
            publicBufferedWriter.flush();
            publicBufferedWriter.close();
            publicFileWriter.close();
            privateBufferedWriter.flush();
            privateBufferedWriter.close();
            privateFileWriter.close();
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
        }
    }

    /**
     * @Description 从文件中输入流中获得密钥(公钥或者私钥[根据传入的地址不同读取不同的文件])字符串
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [keyFilePath]
     * @Return java.lang.String
     **/
    public static String getKeyByFile(String keyFilePath) throws Exception {
        try {
            BufferedReader bufferedReader = new BufferedReader(new FileReader(keyFilePath));
            String readLine = null;
            StringBuilder keyOutStr = new StringBuilder();
            // 读取文件
            while ((readLine = bufferedReader.readLine()) != null) {
                keyOutStr.append(readLine);
            }
            bufferedReader.close();
            // 密钥字符串
            String  keyStr = "";
            if (keyOutStr.toString().indexOf(KEY_AND_VALUE_SEPARATOR) != -1){
                String[] keyOutStrArr = keyOutStr.toString().split(KEY_AND_VALUE_SEPARATOR);
                if (keyOutStrArr != null && keyOutStrArr.length >1){
                    keyStr = keyOutStrArr[1];
                }
            }
            return keyStr;
        } catch (IOException e) {
            throw new Exception("密钥数据流读取错误");
        } catch (NullPointerException e) {
            throw new Exception("密钥输入流为空");
        }
    }

    /**
     * @Description 获取持久的密钥对(直接从密钥文件中读取的)
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param []
     * @Return java.util.Map<java.lang.String,java.lang.Object> 返回持久的公钥和私钥
     **/
    public static Map<String, Object> getLastingKeyPair() throws Exception {
        Map<String, Object> returnMap = new LinkedHashMap<>();
        // 读取文件中的公钥  获取方式为:基础文件路径 + 公钥文件存储地址
        String publicKeyFileStr = RsaUtils.getKeyByFile(PUBLIC_KEY_FILE_ULR);
        if (publicKeyFileStr != null && !publicKeyFileStr.equals("")){
            // 公钥
            returnMap.put(PUBLIC_KEY,publicKeyFileStr);
            log.info("持久化公钥:"+publicKeyFileStr);
        }
        // 读取文件中的私钥 获取方式为:基础文件路径 + 私钥文件存储地址
        String privateKeyFileStr = RsaUtils.getKeyByFile(PRIVATE_KEY_FILE_ULR);
        if (privateKeyFileStr != null && !privateKeyFileStr.equals("")){
            // 私钥
            returnMap.put(PRIVATE_KEY,privateKeyFileStr);
            log.info("持久化私钥:"+privateKeyFileStr);
        }
        return returnMap;
    }

    /************************************************* 密钥初始化、持久化、获取end  *************************************************/



    /**
     * @Description  分组加密/解密
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [rsaMode, dataByteArr, cipher]
     * @param rsaMode RSA模式:encrypt:加密  decrypt:解密
     * @param dataByteArr 需要加密/解密的数据字节数组
     * @param cipher
     * @Return byte[] 完成加密/解密之后的字节数组
     **/
    public static byte[] groupEncryptOrDecrypt(String rsaMode,byte[] dataByteArr, Cipher cipher) throws BadPaddingException, IllegalBlockSizeException {
        // 结果数组
        byte[] returnByteArr = {};
        // 分段处理
        int dataByteArrLength = dataByteArr.length;
        log.info("数据字节数:" + dataByteArrLength);
        // 最大加密/解密字节数,超出最大字节数需要分组加密/解密
        int MAX_BLOCK = 0;
        if (rsaMode != null && !rsaMode.equals("")){
            // 加密模式
            if (RSA_MODE_01.equalsIgnoreCase(rsaMode)){
                // 117
                MAX_BLOCK = ENCRYPT_MAX_SIZE;
            }
            // 解密模式
            if (RSA_MODE_02.equalsIgnoreCase(rsaMode)){
                // 128
                MAX_BLOCK = DECRYPT_MAX_SIZE;
            }
        }
        // 标识
        int offSet = 0;
        // 缓存数组
        byte[] tempByteArr = {};
        // 判断加密/解密字节数 - 标识 是否到达末尾
        while (dataByteArrLength - offSet > 0) {
            // 如果加密/解密字节数 - 标识 > 最大加密/解密字节数
            if (dataByteArrLength - offSet > MAX_BLOCK) {
                // 执行加密/解密  标识位 到 最大加密/解密字节数位
                tempByteArr = cipher.doFinal(dataByteArr, offSet, MAX_BLOCK);
                // 标识 = 自身 + 最大加密/解密字节数
                offSet += MAX_BLOCK;
            } else {
                // 如果加密/解密字节数 - 标识 小于等于 最大加密/解密字节数
                // 执行加密/解密  标识位 到 (加密/解密字节数 - 标志)位
                tempByteArr = cipher.doFinal(dataByteArr, offSet, dataByteArrLength - offSet);
                // 标识 = 加密/解密字节数
                offSet = dataByteArrLength;
            }
            // 创建信息的数组 原来数组的长度  想要得到的新数组的长度(原数组长度 + 缓存数组长度)
            returnByteArr = Arrays.copyOf(returnByteArr, returnByteArr.length + tempByteArr.length);
            // 数组复制 (源数组, 源数组要复制的起始位置, 目标数组, 目标数组放置的起始位置, 要复制的长度)
            // 将缓存数组中的数据 复制到结果数组中
            System.arraycopy(tempByteArr, 0, returnByteArr, returnByteArr.length - tempByteArr.length, tempByteArr.length);
        }
        return returnByteArr;
    }

    /************************************************* 加密start  *************************************************/

    /**
     * @Description 私钥加密(字节数组)
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [data, key]
     * @param data 待加密数据
     * @param key 密钥
     * @Return byte[] 加密之后的数据
     **/
    public static byte[] encryptByPrivateKey(byte[] data,byte[] key) throws Exception{
        // 返回结果
        byte[] result = {};
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
        // 实例化密钥工厂  RSA 算法的
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 生成私钥
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        // 数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        // 加密模式 1
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        // RSA模式 加密模式
        String rsaMode = RSA_MODE_01;
        // 分组加密
        byte[] returnByteArr = RsaUtils.groupEncryptOrDecrypt(rsaMode,data,cipher);
        if (returnByteArr != null && returnByteArr.length > 0){
            result = returnByteArr;
        }
        return result;
    }


    /**
     * @Description 公钥加密(字节数组)
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [data, key]
     * @param data 待加密的数据
     * @param key 密钥
     * @Return byte[] 加密之后的数据
     **/
    public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{
        // 返回结果
        byte[] result = {};
        // 实例化密钥工厂 RSA 算法的
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 初始化公钥
        // 密钥材料转换
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
        // 产生公钥
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        // 数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        // 加密模式
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        // RSA模式 加密模式
        String rsaMode = RSA_MODE_01;
        // 分组加密
        byte[] returnByteArr = RsaUtils.groupEncryptOrDecrypt(rsaMode,data,cipher);
        if (returnByteArr != null && returnByteArr.length > 0){
            result = returnByteArr;
        }
        return result;
    }

    /**
     * @Description 公钥加密(字符串)
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [data, key]
     * @param data 待加密的数据
     * @param key 密钥
     * @Return java.lang.String 加密之后的数据
     **/
    public static String encryptByPublicKey(String data,String key) throws Exception{
        // 返回结果
        StringBuilder result = new StringBuilder("");
        // 实例化密钥工厂 RSA 算法的
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 初始化公钥
        // 密钥材料转换
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(key));
        // 产生公钥
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        // 数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        // 加密模式
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        // 将数据字符串转换为字节数组
        byte[] dataByteArr = data.getBytes();
        // RSA模式 加密模式
        String rsaMode = RSA_MODE_01;
        // 分组加密
        byte[] returnByteArr = RsaUtils.groupEncryptOrDecrypt(rsaMode,dataByteArr,cipher);
        if (returnByteArr != null && returnByteArr.length > 0){
            result.append(Base64.encode(returnByteArr));
        }
        return result.toString();
    }

    /**
     * @Description 私钥加密(字符串)
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [data, key]
     * @param data 待加密数据
     * @param key 密钥
     * @Return java.lang.String 加密之后的数据
     **/
    public static String encryptByPrivateKey(String data,String key) throws Exception{
        // 返回结果
        StringBuilder result = new StringBuilder("");
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decode(key));
        // 实例化密钥工厂  RSA 算法的
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 生成私钥
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        // 数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        // 加密模式 1
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        // 将数据字符串转换为字节数组
        byte[] dataByteArr = data.getBytes();
        // RSA模式 加密模式
        String rsaMode = RSA_MODE_01;
        // 分组加密
        byte[] returnByteArr = RsaUtils.groupEncryptOrDecrypt(rsaMode,dataByteArr,cipher);
        if (returnByteArr != null && returnByteArr.length > 0){
            result.append(Base64.encode(returnByteArr));
        }
        return result.toString();
    }

    /************************************************* 加密end  *************************************************/


    /************************************************* 解密start  *************************************************/

    /**
     * @Description 私钥解密(字节数组)
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [data, key]
     * @param data 待解密数据
     * @param key 密钥
     * @Return byte[] 解密之后的数据
     **/
    public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{
        // 返回的结果字节数组
        byte[] resultByteArr = {};
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
        // 实例化密钥工厂 RSA算法的
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 生成私钥
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        // 数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        // 解密模式
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        // RSA模式 解密模式
        String rsaMode = RSA_MODE_02;
        // 分组解密
        byte[] returnBytes = RsaUtils.groupEncryptOrDecrypt(rsaMode,data,cipher);
        if (returnBytes != null && resultByteArr.length >0){
            resultByteArr = returnBytes;
        }
        return resultByteArr;
    }

    /**
     * @Description 公钥解密(字节数组)
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [data, key]
     * @param data 待解密数据
     * @param key 密钥
     * @Return byte[] 解密之后的数据
     **/
    public static byte[] decryptByPublicKey(byte[] data,byte[] key) throws Exception{
        // 返回的结果字节数组
        byte[] resultByteArr = {};
        // 实例化密钥工厂 RSA算法的
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 初始化公钥
        // 密钥材料转换
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
        // 产生公钥
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        // 数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        // 解密模式
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        // RSA模式 解密模式
        String rsaMode = RSA_MODE_02;
        // 分组解密
        byte[] returnBytes = RsaUtils.groupEncryptOrDecrypt(rsaMode,data,cipher);
        if (returnBytes != null && resultByteArr.length >0){
            resultByteArr = returnBytes;
        }
        return resultByteArr;
    }

    /**
     * @Description 私钥解密(字符串)
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [data, key]
     * @param data 待解密数据
     * @param key 密钥
     * @Return java.lang.String 解密之后的数据
     **/
    public static String decryptByPrivateKey(String data,String key) throws Exception{
        // 解密之后的明文字符串
        StringBuilder result = new StringBuilder("");
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decode(key));
        // 实例化密钥工厂 RSA算法的
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 生成私钥
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        // 数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        // 解密模式
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        // 将字符串数据转换为字节数组
        byte[] dataByteArr = Base64.decode(data);
        // RSA模式 解密模式
        String rsaMode = RSA_MODE_02;
        // 分组解密
        byte[] resultBytes = RsaUtils.groupEncryptOrDecrypt(rsaMode,dataByteArr,cipher);
        // 给返回结果赋值
        // TODO 特别注意: 本处将字节数组装换为字符串的时候,必须使用 new String()方法,不能使用toString()方法
        // TODO toString()方法是调用的对象本身的,也就是继承或者重写的object.toString()方法,如果是byte[] b,那么返回的是b的内存地址。
        // TODO new String()方法是使用虚拟机默认的编码base返回对应的字符。
        result.append(new String(resultBytes));
        return result.toString();
    }

    /**
     * @Description 公钥解密(字节数组)
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [data, key]
     * @param data 待解密数据
     * @param key 密钥
     * @Return ava.lang.String 解密之后的数据
     **/
    public static String decryptByPublicKey(String data,String key) throws Exception{
        // 解密之后的明文字符串
        StringBuilder result = new StringBuilder("");
        // 实例化密钥工厂 RSA算法的
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        // 初始化公钥
        // 密钥材料转换
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(key));
        // 产生公钥
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        // 数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        // 解密模式
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        // 将字符串数据转换为字节数组
        byte[] dataByteArr = Base64.decode(data);
        // RSA模式 解密模式
        String rsaMode = RSA_MODE_02;
        // 分组解密
        byte[] resultBytes = RsaUtils.groupEncryptOrDecrypt(rsaMode,dataByteArr,cipher);
        // 给返回结果赋值
        // TODO 特别注意: 本处将字节数组装换为字符串的时候,必须使用 new String()方法,不能使用toString()方法
        // TODO toString()方法是调用的对象本身的,也就是继承或者重写的object.toString()方法,如果是byte[] b,那么返回的是b的内存地址。
        // TODO new String()方法是使用虚拟机默认的编码base返回对应的字符。
        result.append(new String(resultBytes));
        return result.toString();
    }

    /************************************************* 解密end  *************************************************/


    /************************************************* 生成签名、签名验证start  *************************************************/

    /**
     * @Description 生成签名
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [content, privateKey]
     * @param content 待签名的数据原文
     * @param privateKey 私钥字符串
     * @Return java.lang.String 签名值
     **/
    public static String generatorSign(String content, String privateKey) {
        String signStr = "";
        try {
            // 取得私钥
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
            // 实例化密钥工厂 RSA算法的
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            // 生成私钥
            PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            // 实例化签名
            Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
            // 初始化签名
            signature.initSign(priKey);
            // 签名更新
            signature.update(content.getBytes());
            // 生成的签名字节数组
            byte[] signByteArr = signature.sign();
            // 返回Base64编码的签名字符串
            signStr = Base64.encode(signByteArr);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return signStr;
    }

    /**
     * @Description 检查签名是否合法性
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [content, sign, publicKey]
     * @param content 待签名的数据原文
     * @param sign 签名值
     * @param publicKey 私钥
     * @Return boolean 是否合法
     **/
    public static boolean checkSignVerify(String content, String sign, String publicKey) {
        boolean isOK = false;
        try {
            // 取得公钥
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(publicKey));
            // 实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            // 生成公钥
            PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);
            // 实例化签名
            Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
            // 签名验证初始化
            signature.initVerify(pubKey);
            // 更新签名
            signature.update(content.getBytes());
            // 验证签名是否合法
            isOK = signature.verify(Base64.decode(sign));
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return isOK;
    }

    /************************************************* 生成签名、签名验证end  *************************************************/

}
RsaUtils.java

Base64类可以使用java自带的Base64替代:

package com.sxy.rsademo.utils;

public final class Base64 {

    static private final int BASELENGTH = 128;
    static private final int LOOKUPLENGTH = 64;
    static private final int TWENTYFOURBITGROUP = 24;
    static private final int EIGHTBIT = 8;
    static private final int SIXTEENBIT = 16;
    static private final int FOURBYTE = 4;
    static private final int SIGN = -128;
    static private final char PAD = '=';
    static private final boolean fDebug = false;
    static final private byte[] base64Alphabet = new byte[BASELENGTH];
    static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];

    static {
        for (int i = 0; i < BASELENGTH; ++i) {
            base64Alphabet[i] = -1;
        }
        for (int i = 'Z'; i >= 'A'; i--) {
            base64Alphabet[i] = (byte) (i - 'A');
        }
        for (int i = 'z'; i >= 'a'; i--) {
            base64Alphabet[i] = (byte) (i - 'a' + 26);
        }

        for (int i = '9'; i >= '0'; i--) {
            base64Alphabet[i] = (byte) (i - '0' + 52);
        }

        base64Alphabet['+'] = 62;
        base64Alphabet['/'] = 63;

        for (int i = 0; i <= 25; i++) {
            lookUpBase64Alphabet[i] = (char) ('A' + i);
        }

        for (int i = 26, j = 0; i <= 51; i++, j++) {
            lookUpBase64Alphabet[i] = (char) ('a' + j);
        }

        for (int i = 52, j = 0; i <= 61; i++, j++) {
            lookUpBase64Alphabet[i] = (char) ('0' + j);
        }
        lookUpBase64Alphabet[62] = (char) '+';
        lookUpBase64Alphabet[63] = (char) '/';

    }

    private static boolean isWhiteSpace(char octect) {
        return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
    }

    private static boolean isPad(char octect) {
        return (octect == PAD);
    }

    private static boolean isData(char octect) {
        return (octect < BASELENGTH && base64Alphabet[octect] != -1);
    }

    /**
     * Encodes hex octects into Base64
     *
     * @param binaryData Array containing binaryData
     * @return Encoded Base64 array
     */
    public static String encode(byte[] binaryData) {

        if (binaryData == null) {
            return null;
        }

        int lengthDataBits = binaryData.length * EIGHTBIT;
        if (lengthDataBits == 0) {
            return "";
        }

        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
        int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
        char encodedData[] = null;

        encodedData = new char[numberQuartet * 4];

        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;

        int encodedIndex = 0;
        int dataIndex = 0;
        if (fDebug) {
            System.out.println("number of triplets = " + numberTriplets);
        }

        for (int i = 0; i < numberTriplets; i++) {
            b1 = binaryData[dataIndex++];
            b2 = binaryData[dataIndex++];
            b3 = binaryData[dataIndex++];

            if (fDebug) {
                System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
            }

            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);

            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
            byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);

            if (fDebug) {
                System.out.println("val2 = " + val2);
                System.out.println("k4   = " + (k << 4));
                System.out.println("vak  = " + (val2 | (k << 4)));
            }

            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
        }

        // form integral number of 6-bit groups  
        if (fewerThan24bits == EIGHTBIT) {
            b1 = binaryData[dataIndex];
            k = (byte) (b1 & 0x03);
            if (fDebug) {
                System.out.println("b1=" + b1);
                System.out.println("b1<<2 = " + (b1 >> 2));
            }
            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
            encodedData[encodedIndex++] = PAD;
            encodedData[encodedIndex++] = PAD;
        } else if (fewerThan24bits == SIXTEENBIT) {
            b1 = binaryData[dataIndex];
            b2 = binaryData[dataIndex + 1];
            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);

            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);

            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
            encodedData[encodedIndex++] = PAD;
        }

        return new String(encodedData);
    }

    /**
     * Decodes Base64 data into octects
     *
     * @param encoded string containing Base64 data
     * @return Array containind decoded data.
     */
    public static byte[] decode(String encoded) {

        if (encoded == null) {
            return null;
        }

        char[] base64Data = encoded.toCharArray();
        // remove white spaces  
        int len = removeWhiteSpace(base64Data);

        if (len % FOURBYTE != 0) {
            // should be divisible by four
            return null;
        }

        int numberQuadruple = (len / FOURBYTE);

        if (numberQuadruple == 0) {
            return new byte[0];
        }

        byte decodedData[] = null;
        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
        char d1 = 0, d2 = 0, d3 = 0, d4 = 0;

        int i = 0;
        int encodedIndex = 0;
        int dataIndex = 0;
        decodedData = new byte[(numberQuadruple) * 3];

        for (; i < numberQuadruple - 1; i++) {

            if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
                    || !isData((d3 = base64Data[dataIndex++]))
                    || !isData((d4 = base64Data[dataIndex++]))) {
                return null;
            }//if found "no data" just return null  

            b1 = base64Alphabet[d1];
            b2 = base64Alphabet[d2];
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];

            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
        }

        if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
            //if found "no data" just return null
            return null;
        }

        b1 = base64Alphabet[d1];
        b2 = base64Alphabet[d2];

        d3 = base64Data[dataIndex++];
        d4 = base64Data[dataIndex++];
        // Check if they are PAD characters
        if (!isData((d3)) || !isData((d4))) {
            if (isPad(d3) && isPad(d4)) {
                // last 4 bits should be zero
                if ((b2 & 0xf) != 0)
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 1];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                return tmp;
            } else if (!isPad(d3) && isPad(d4)) {
                b3 = base64Alphabet[d3];
                //last 2 bits should be zero
                if ((b3 & 0x3) != 0)
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 2];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                return tmp;
            } else {
                return null;
            }
        } else {
            //No PAD e.g 3cQl
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];
            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);

        }

        return decodedData;
    }

    /**
     * remove WhiteSpace from MIME containing encoded Base64 data.
     *
     * @param data  the byte array of base64 data (with WS)
     * @return      the new length
     */
    private static int removeWhiteSpace(char[] data) {
        if (data == null) {
            return 0;
        }

        // count characters that's not whitespace
        int newSize = 0;
        int len = data.length;
        for (int i = 0; i < len; i++) {
            if (!isWhiteSpace(data[i])) {
                data[newSize++] = data[i];
            }
        }
        return newSize;
    }

}
Base64.java

 转型工具类:

package com.sxy.rsademo.utils;

/**
 * @Description 转型工具类
 * @Author SuXingYong
 * @Date 2020/7/11 23:35
 **/
public final class CastUtils {

    /**
     * @Description 转为String 型 默认为空
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [obj]
     * @param obj
     * @Return java.lang.String
     **/
    public static String castString(Object obj) {
        return CastUtils.castString(obj, "");
    }

    /**
     * @Description 转为String 型(提供默认值)
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [obj, defaultValue]
     * @param obj
     * @param defaultValue 默认值
     * @Return java.lang.String
     **/
    public static String castString(Object obj, String defaultValue) {
        return obj != null ? String.valueOf(obj) : defaultValue;
    }
}
CastUtils.java

统一返回常量类:

package com.sxy.rsademo.utils;

/**
 * @Description: 返回常量
 * @Author: SuXingYong
 * @Date 2020/7/11 23:35
 **/
public class ReturnConstant {
    /** 返回值常量 - 成功 **/
    public final static String SUCCESS = "success";

    /** 返回值常量 - 失败 **/
    public final static String ERROR = "error";
}
ReturnConstant.java

HttpClientUtils工具类:

package com.sxy.rsademo.utils;

import com.alibaba.fastjson.JSON;
import com.sxy.rsademo.rsa.RsaUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;

/**
 * @Description HttpClient 工具类
 * @Author SuXingYong
 * @Date 2020/7/11 23:35
 **/
@Slf4j
public class HttpClientUtils {

    /** 目标服务器 - URL - 01 **/
    public final static String CLIENT_URL_01 = "http://localhost:9009/target-server/data/receive";
    /** 目标服务器 - 数据 - 键名 **/
    public final static String SERVER_DATA_KEY = "dataJson";
    /** 目标服务器 - 签名 - 键名 **/
    public final static String SERVER_SIGN_KEY = "sign";


    public static void main(String[] args) {
        try {
            String url = "";
            Map<String, String> parameterMap = new LinkedHashMap<>();
            // 发送数据
            Map<String, String> resultMap = HttpClientUtils.sendDataToTargetServerForOne(url,parameterMap);
            for (Map.Entry<String, String> result : resultMap.entrySet()){
               log.info("result==》 "+result.getKey()+": "+result.getValue());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 构造数据
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param []
     * @Return java.util.Map<java.lang.String,java.lang.String>
     **/
    public static Map<String,String> createData() throws UnsupportedEncodingException {
        Map<String, String> returnMap = new LinkedHashMap<>();
        Map<String, String> dataMap = new LinkedHashMap<>();
        dataMap.put("id","11eh-9b58-af45b5c8-b5e2-9d0036e9473z");
        dataMap.put("name","小明");
        dataMap.put("loginName","xiaoming");
        dataMap.put("phone","12345678901");
        dataMap.put("time","2020-07-12 00:33:27");
        dataMap.put("content","随便整了些内容,就验证一下。");
        for (Map.Entry<String, String> data : dataMap.entrySet()){
            returnMap.put(data.getKey(),URLEncoder.encode(data.getValue(),"UTF-8"));
        }
        return returnMap;
    }

    /**
     * @Description 单条发送数据
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [url,parameterMap]
     * @Return java.util.Map<java.lang.String,java.lang.String>
     **/
    public static Map<String, String> sendDataToTargetServerForOne(String url,Map<String, String> parameterMap) throws Exception {
        // 返回结果集
        Map<String, String> returnMap = new LinkedHashMap<>();
        // 请求参数 传入参数结果集为空的时候就直接使用默认值
        Map<String, String>  requestMap = HttpClientUtils.createData();
        if (parameterMap != null && parameterMap.size() >0){
            // 清空默认值
            requestMap = new LinkedHashMap<>();
            // 对参数集合的值进行url编码
            for (Map.Entry<String, String> param : parameterMap.entrySet()){
                requestMap.put(param.getKey(),URLEncoder.encode(param.getValue(),"UTF-8"));
            }
        }
        if (requestMap != null && requestMap.size() >0){
            // 数据参数字符串
            StringBuilder dataStr  = new StringBuilder("");
            // 遍历参数集合并拼接成字符串
            for (Map.Entry<String, String> map : requestMap.entrySet()){
                // 键名
                String dataKey = map.getKey();
                // 键值
                String dataValue = map.getValue();
                dataStr.append(dataKey).append("=");
                dataStr.append(dataValue);
                dataStr.append("&");
            }
           log.info("send==》 dataStr:"+dataStr);
            // 去除最后一个&符号
            String paramStr = dataStr.toString().substring(0, dataStr.length() - 1);
           log.info("send==》 paramStr:"+paramStr);

            // 服务器原文数据
            //requestMap.put("originalTextData",paramStr);

            // 将数据转化为json字符串
            String dataJson = JSON.toJSONString(requestMap);
           log.info("send==》 dataJson: "+dataJson);
            // 重置请求参数集合
            requestMap = new LinkedHashMap<>();
            // 将json数据放到请求参数集合中
            //requestMap.put("data",dataJson);

            // 密钥对
            Map<String,Object> keyMap = RsaUtils.getLastingKeyPair();

            // 使用持久化公钥对数据进行加密
            String cipherTextData = RsaUtils.encryptByPublicKey(dataJson, CastUtils.castString(keyMap.get(RsaUtils.PUBLIC_KEY)));
           log.info("send==》  cipherTextData: "+cipherTextData);
            // 服务器密文数据
            requestMap.put("data",cipherTextData);

            // 使用持久化私钥生成签名
            String sign = RsaUtils.generatorSign(cipherTextData, CastUtils.castString(keyMap.get(RsaUtils.PRIVATE_KEY)));
            //
           log.info("send==》  sign: "+sign);

            // 请求参数中需带上签名字符串
            requestMap.put(SERVER_SIGN_KEY, sign);

            // 将请求参数转化为json字符串
            String requestJson = JSON.toJSONString(requestMap);
           log.info("send==》  requestJson:"+requestJson);
            // 请求地址 没有传入的时候就使用默认值
            String requestUrl = CLIENT_URL_01;
            if (url != null && url != ""){
                requestUrl = url;
               log.info("send==》 requestUrl:"+requestUrl);
            }
            if (requestUrl != null && requestUrl != ""){
                requestMap = new LinkedHashMap<>();
                requestMap.put(SERVER_DATA_KEY, requestJson);
                if (requestMap != null && requestMap.size() >0){
                    //发送POST请求 parameterMap模式
                    returnMap = HttpClientUtils.sendPostRequest(requestUrl,requestMap);
                }else{
                    returnMap.put(ReturnConstant.ERROR,"请求数据参数为空,不支持");
                }

                //if (requestJson != null && requestJson != ""){
                    // 发送POST请求 json模式
                //    returnMap = HttpClientUtils.sendPostRequest(requestUrl,requestJson);
                //}else{
                //    returnMap.put(ReturnConstant.ERROR,"请求数据参数为空,不支持");
                //}
            }else{
                returnMap.put(ReturnConstant.ERROR,"请求地址为空,不支持");
            }
        }else{
            returnMap.put(ReturnConstant.ERROR,"发送数据为空,不支持");
        }
        return returnMap;
    }

    /**
     * @Description 批量发送数据
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [url, dataList]
     * @Return java.util.Map<java.lang.String,java.lang.String>
     **/
    public static Map<String,String> sendDataToTargetServerForList(String url, List<Map<String,String>> dataList) throws Exception{
        // 返回结果集
        Map<String, String> returnMap = new LinkedHashMap<>();
        // 请求参数集合
        Map<String, String>  requestMap = new LinkedHashMap<>();
        if (dataList != null && dataList.size() >0){
            // 缓存列表
            List<Map<String, String>> cacheList = new ArrayList<>();
            for (int i = 0 ; i < dataList.size() ; i++){
                // 对参数进行编码之后的新集合
                Map<String, String> newDataMap = new LinkedHashMap<>();
                Map<String, String> dataMap = dataList.get(i);
                // 对参数集合的值进行url编码
                for (Map.Entry<String, String> data : dataMap.entrySet()){
                    newDataMap.put(data.getKey(),URLEncoder.encode(data.getValue(),"UTF-8"));
                }
                if (newDataMap != null && newDataMap.size() >0){
                    // 将编码后的新集合放到缓存数组中
                    cacheList.add(newDataMap);
                }
            }
            if (cacheList != null && cacheList.size() >0){
                // 重置数据列表
                dataList = new ArrayList<>();
                dataList = cacheList;
            }

            // 将数据转化为json字符串
            String dataJson = JSON.toJSONString(dataList);
            log.info("send==》 dataJson: "+dataJson);
            // 将数据json字符串放到请求参数中
            //requestMap.put("originalTextData",dataJson);


            // 密钥对
            Map<String,Object> keyMap = RsaUtils.getLastingKeyPair();

            // 使用持久化公钥对数据进行加密
            String cipherTextData = RsaUtils.encryptByPublicKey(dataJson, CastUtils.castString(keyMap.get(RsaUtils.PUBLIC_KEY)));
            log.info("send==》  cipherTextData: "+cipherTextData);
            // 发送密文数据
            requestMap.put("data",cipherTextData);

            // 使用持久化私钥生成签名
            String sign = RsaUtils.generatorSign(cipherTextData, CastUtils.castString(keyMap.get(RsaUtils.PRIVATE_KEY)));
            //
            log.info("send==》  sign: "+sign);

            // 请求参数中需带上签名字符串
            requestMap.put(SERVER_SIGN_KEY, sign);

            // 将请求参数转化为json字符串
            String requestJson = JSON.toJSONString(requestMap);
            log.info("send==》  requestJson:"+requestJson);
            // 请求地址 没有传入的时候就使用默认值
            String requestUrl = CLIENT_URL_01;
            if (url != null && url != ""){
                requestUrl = url;
                log.info("send==》 requestUrl:"+requestUrl);
            }
            if (requestUrl != null && requestUrl != ""){
                if (requestJson != null && requestJson != ""){
                    // 发送POST请求 json模式
                    returnMap = HttpClientUtils.sendPostRequest(requestUrl,requestJson);
                }else{
                    returnMap.put(ReturnConstant.ERROR,"请求数据参数为空,不支持");
                }
            }else {
                returnMap.put(ReturnConstant.ERROR, "请求地址为空,不支持");
            }
        }else{
            returnMap.put(ReturnConstant.ERROR,"数据为空,不支持");
        }
        return returnMap;
    }

    /**
     * @Description 发送POST请求 parameterMap模式
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [url, json]
     * @Return java.util.Map<java.lang.String,java.lang.String>
     **/
    public static Map<String, String> sendPostRequest(String url,Map<String, String> parameterMap){
        // 返回结果
        Map<String, String> returnMap = new LinkedHashMap<>();
        OutputStream out = null;
        BufferedReader in = null;
        HttpURLConnection conn = null;
        String result = "";
        try {
            StringBuilder data = new StringBuilder();
            for (Map.Entry<String, String> dataKeyValue : parameterMap.entrySet()) {
                String dataName = dataKeyValue.getKey();
                String dataValue = dataKeyValue.getValue();
                data.append(dataName).append("=");
                //data.append(dataValue);
                // 转换为UTF-8编码
                data.append(URLEncoder.encode(dataValue, "UTF-8"));
                data.append("&");
            }
            data.append("sendTime=").append(System.currentTimeMillis());
           log.info("send==》 parameterMapStr: "+data.toString());
            byte[] entity = data.toString().getBytes();
            conn = (HttpURLConnection)new URL(url).openConnection();
            conn.setUseCaches(false);
            // 10000
            conn.setConnectTimeout(10000);
            // POST
            conn.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            conn.setRequestProperty("Content-Length", String.valueOf(entity.length));

            out = conn.getOutputStream();
            // 获取URLConnection对象对应的输出流
            out = conn.getOutputStream();
            // 发送请求参数
            out.write(entity);
            // flush输出流的缓冲
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            returnMap.put(ReturnConstant.SUCCESS,result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }

        }
        return returnMap;
    }

    /**
     * @Description 发送POST请求 json字符串模式
     * @Author SuXingYong
     * @Date 2020/7/11 23:35
     * @Param [url, json]
     * @Return java.util.Map<java.lang.String,java.lang.String>
     **/
    public static Map<String, String> sendPostRequest(String url,String json){
        // 返回结果集
        Map<String, String> returnMap = new LinkedHashMap<>();
        // 创建HttpClient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
           log.info("send==》 json:"+json);
            // 创建请求内容
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求
            response = httpClient.execute(httpPost);
            returnMap.put(ReturnConstant.SUCCESS, EntityUtils.toString(response.getEntity(), "utf-8"));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return returnMap;
    }

    /**
     * 获取sendPostRequest请求的Json数据
     */
    private String getRequestPostData(HttpServletRequest request) throws IOException {
        int contentLength = request.getContentLength();
        if (contentLength < 0) {
            return null;
        }
        byte buffer[] = new byte[contentLength];
        for (int i = 0; i < contentLength;) {
            int len = request.getInputStream().read(buffer, i, contentLength - i);
            if (len == -1) {
                break;
            }
            i += len;
        }
        return new String(buffer, "utf-8");
    }

}
HttpClientUtils.java

SpringBoot项目运行入口类:

package com.sxy.rsademo;

import com.sxy.rsademo.rsa.RsaUtils;
import com.sxy.rsademo.utils.HttpClientUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.Map;

@Slf4j
@SpringBootApplication
public class RsaDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(RsaDemoApplication.class, args);
        // 初始化密钥对,并持久化存储
        RsaUtils.initKey();
        try {
            // 获取持久化密钥对
            Map<String,Object> keyMap =  RsaUtils.getLastingKeyPair();
            for (Map.Entry<String,Object> entry :keyMap.entrySet()){
                log.info("keyMap==》 "+entry.getKey()+": "+entry.getValue());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 发送数据进行测试
        HttpClientUtils.main(args);
    }

}
RsaDemoApplication.java

pom.xml  maven依赖文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.sxy</groupId>
    <artifactId>rsa-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>rsa-demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <fastjson.version>1.2.62</fastjson.version>
        <httpClient.version>4.5.12</httpClient.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>${httpClient.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
pom.xml

运行结果:

 

 密钥对生成成功:

私钥持久化文件:

 

 公钥持久化文件:

 

 至此,RSA算法的密钥对的初始化,持久化保存、读取,数据签名、加密、发送等基本功能已完成;

 关于数据如何接收、验证签名以及解密将在下一篇文章中继续分享;

 

posted @ 2020-07-12 01:21  叶凌霄  阅读(567)  评论(0编辑  收藏  举报