第一步:在本地安装OpenSSL(安装步骤省略),打开/bin目录下的openssl.exe文件。输入一下命令。

1.生成RSA私钥
genrsa -out rsa_private_key.pem 1024
2.把RSA私钥转换成PKCS8格式
pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
3.生成公钥
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

第二步:将pkcs8.pem文件和rsa_public_key.pem文件的绝对路径取到。
第三步:在Controller层新建2个方法。
1.对返回值进行加密(公钥)。@Encrypt :对返回值进行加密的注解

//对返回的字符串进行加密
  @Encrypt
  @GetMapping("/encryption")
  public String encryption() {
    return "成功";
  //对返回的实体类进行加密
  @Encrypt
  @GetMapping("/encryption")
  public 实体ShiTi encryption() {
    ShiTi shiTi = new ShiTi ();
    shiTi.setvalue("值");
    return shiTi;

2.对请求参数进行解密(私钥)。@Decrypt:对接收数据进行解密的注解

@Decrypt
  @PostMapping("/decryption")
  public String Decryption(@RequestBody String a(上一个方法加密之后的数据)){
    return a(解密之后的数据);
  }

第四步:在一个项目同级目录下新建文件夹存放2个注解文件。

//解密
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Decrypt {
}

//加密
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Encrypt {
}

第五步:三个加解密的工具类。

/**
 * 私钥加解密【服务器使用】
 */
@Component
public class PrivateKeyUtils {

  /**
   * 服务端:私钥加密
   * @param privatePath
   * @param plainText
   */
  public static String encrypt(String privatePath, String plainText) throws Exception {
    try {
      RSAPrivateKey privateKey = RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadKeyByFile(privatePath));
      byte[] cipherData = RSAEncrypt.encrypt(privateKey, plainText.getBytes());
      Base64 base64 = new Base64();
      String cipher = new String(base64.encode(cipherData));
      return cipher;
    } catch (Exception e) {
      e.printStackTrace();
      //return "error";
      throw new Exception(e.getMessage());
    }
  }

  /**
   * 服务端:私钥解密
   */
  public static String decrypt(String privatePath, String cipherText) {
    try {
      Base64 base64 = new Base64();
      RSAPrivateKey privateKey = RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadKeyByFile(privatePath));
      byte[] res = RSAEncrypt.decrypt(privateKey, base64.decode(cipherText));
      String plain = new String(res);
      return plain;
    } catch (Exception e) {
      e.printStackTrace();
      return "error";
    }
  }
}
/**
 * 公钥加解密【客户端使用】
 */
public class PublicKeyUtils {

  /**
   * 客户端:公钥加密
   * @param publicPath
   * @param plainText
   */
  public static String encrypt(String publicPath, String plainText){

    if (StringUtils.isEmpty(publicPath)) {
      throw new IllegalArgumentException("公钥为空");
    }
    if (new File(publicPath).exists() == false) {
      throw new IllegalArgumentException("公钥不存在");
    }
    if (StringUtils.isEmpty(plainText)) {
      throw new IllegalArgumentException("数据为空");
    }
    try {
      RSAPublicKey publicKey = RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadKeyByFile(publicPath));
      byte[] cipherData = RSAEncrypt.encrypt(publicKey, plainText.getBytes());
      Base64 base64 = new Base64();
      String cipher = new String(base64.encode(cipherData));
      return cipher;
    } catch (Exception e) {
      e.printStackTrace();
      return "error";
    }
  }
  /**
   * 客户端:公钥解密
   * @param publicPath
   * @param cipherText
   * @return
   */
  public static String decrypt(String publicPath, String cipherText) {
    try {
      Base64 base64 = new Base64();
      RSAPublicKey publicKey = RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadKeyByFile(publicPath));
      byte[] res = RSAEncrypt.decrypt(publicKey, base64.decode(cipherText));
      String plain = new String(res);
      return plain;
    } catch (Exception e) {
      e.printStackTrace();
      return "error";
    }
  }
}
/**
 * RSA加密组件
 */
public class RSAEncrypt {
  private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6',
    '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  // RSA最大加密明文大小
  private static final int MAX_ENCRYPT_BLOCK = 117;
  // RSA最大解密密文大小
  private static final int MAX_DECRYPT_BLOCK = 128;
  /**
   * 随机生成密钥对
   * @param filePath   密钥存放路径
   * @param filePrefix 密钥名称前缀
   */
  public static void genKeyPair(String filePath, String filePrefix) {
    KeyPairGenerator keyPairGen = null;
    try {
      keyPairGen = KeyPairGenerator.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    }
    // 初始化密钥对生成器,密钥大小为96-1024位
    keyPairGen.initialize(1024, new SecureRandom());
    // 生成一个密钥对,保存在keyPair中
    KeyPair keyPair = keyPairGen.generateKeyPair();
    // 得到私钥
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    // 得到公钥
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

    try {
      // 得到公钥字符串
      Encoder base64 = Base64.getEncoder();
      String publicKeyString = new String(base64.encode(publicKey.getEncoded()));
      // 得到私钥字符串
      String privateKeyString = new String(base64.encode(privateKey.getEncoded()));
      // 将密钥对写入到文件
      StringBuffer publicKeyName = new StringBuffer();
publicKeyName.append(filePath).append("/").append(filePrefix).append("_public_key.pem");
      StringBuffer privateKeyName = new StringBuffer();
privateKeyName.append(filePath).append("/").append(filePrefix).append("_private_key.pem");

      FileWriter pubfw = new FileWriter(new String(publicKeyName));
      FileWriter prifw = new FileWriter(new String(privateKeyName));
      BufferedWriter pubbw = new BufferedWriter(pubfw);
      BufferedWriter pribw = new BufferedWriter(prifw);
      pubbw.write(publicKeyString);
      pribw.write(privateKeyString);
      pubbw.flush();
      pubbw.close();
      pubfw.close();
      pribw.flush();
      pribw.close();
      prifw.close();

      System.out.println("公钥是:" + publicKeyName + "私钥是:" + privateKeyName);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 从文件中输入流中加载密钥
   * @param path 公钥输入流
   * @throws Exception 加载公钥时产生的异常
   */
  public static String loadKeyByFile(String path) throws Exception {
    try {
      BufferedReader br = new BufferedReader(new FileReader(path));
      String readLine = null;
      StringBuilder sb = new StringBuilder();
      while ((readLine = br.readLine()) != null) {
        if (readLine.charAt(0) == '-') {
          continue;
        } else {
          sb.append(readLine);
          sb.append('\r');
        }
      }
      br.close();
      return sb.toString();
    } catch (IOException e) {
      e.printStackTrace();
      throw new Exception("密钥数据流读取错误");
    } catch (NullPointerException e) {
      throw new Exception("密钥输入流为空");
    }
  }

  /**
   * 从字符串中加载公钥
   * @param publicKeyStr 公钥数据字符串
   * @throws Exception 加载公钥时产生的异常
   */
  public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr)
    throws Exception {
    try {
      Decoder decoder = Base64.getMimeDecoder();//注不要使用.getDecoder();
      byte[] buffer = decoder.decode(publicKeyStr);

      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
      return (RSAPublicKey) keyFactory.generatePublic(keySpec);
    } catch (NoSuchAlgorithmException e) {
      throw new Exception("无此算法");
    } catch (InvalidKeySpecException e) {
      throw new Exception("公钥非法");
    } catch (NullPointerException e) {
      throw new Exception("公钥数据为空");
    }
  }

  /**
   * 从字符串中加载私钥
   */
  public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)
    throws Exception {
    try {
      Decoder base64Decoder = Base64.getMimeDecoder();
      byte[] buffer = base64Decoder.decode(privateKeyStr);

      PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
      throw new Exception("无此算法");
    } catch (InvalidKeySpecException e) {
      e.printStackTrace();
      throw new Exception("私钥非法");
    } catch (NullPointerException e) {
      e.printStackTrace();
      throw new Exception("私钥数据为空");
    }
  }

  /**
   * 公钥加密过程
   * @param publicKey     公钥
   * @param plainTextData 明文数据
   * @throws Exception 加密过程中的异常信息
   */
  public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)
    throws Exception {
    if (publicKey == null) {
      throw new Exception("加密公钥为空, 请设置");
    }
    Cipher cipher = null;
    try {
      // 使用默认RSA
      cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.ENCRYPT_MODE, publicKey);
      // 明文数据的长度
      int inputLen = plainTextData.length;
      int offSet = 0;
      int i = 0;
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      byte[] output = null;
      // 对数据分段加密
      while (inputLen - offSet > 0) {
        if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
          output = cipher.doFinal(plainTextData, offSet, MAX_ENCRYPT_BLOCK);
        } else {
          output = cipher.doFinal(plainTextData, offSet, inputLen - offSet);
        }
        out.write(output, 0, output.length);
        i++;
        offSet = i * MAX_ENCRYPT_BLOCK;
      }
      byte[] encryptedData = out.toByteArray();
      out.close();
      return encryptedData;
      //return output;
    } catch (NoSuchAlgorithmException e) {
      throw new Exception("无此加密算法");
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
      return null;
    } catch (InvalidKeyException e) {
      throw new Exception("加密公钥非法,请检查");
    } catch (IllegalBlockSizeException e) {
      throw new Exception("明文长度非法");
    } catch (BadPaddingException e) {
      throw new Exception("明文数据已损坏");
    }
  }

  /**
   * 私钥加密过程
   *
   * @param privateKey    私钥
   * @param plainTextData 明文数据
   * @return
   * @throws Exception 加密过程中的异常信息
   */
  public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)
    throws Exception {
    if (privateKey == null) {
      throw new Exception("加密私钥为空, 请设置");
    }
    Cipher cipher = null;
    try {
      // 使用默认RSA
      cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.ENCRYPT_MODE, privateKey);

      // 明文数据的长度
      int inputLen = plainTextData.length;
      int offSet = 0;
      int i = 0;

      ByteArrayOutputStream out = new ByteArrayOutputStream();
      byte[] output = null;

      // 对数据分段加密
      while (inputLen - offSet > 0) {
        if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
          output = cipher.doFinal(plainTextData, offSet, MAX_ENCRYPT_BLOCK);
        } else {
          output = cipher.doFinal(plainTextData, offSet, inputLen - offSet);
        }
        out.write(output, 0, output.length);
        i++;
        offSet = i * MAX_ENCRYPT_BLOCK;
      }

      byte[] encryptedData = out.toByteArray();
      out.close();

      return encryptedData;
    } catch (NoSuchAlgorithmException e) {
      throw new Exception("无此加密算法");
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
      return null;
    } catch (InvalidKeyException e) {
      throw new Exception("加密私钥非法,请检查");
    } catch (IllegalBlockSizeException e) {
      throw new Exception("明文长度非法");
    } catch (BadPaddingException e) {
      throw new Exception("明文数据已损坏");
    }
  }

  /**
   * 私钥解密过程
   * @param privateKey 私钥
   * @param cipherData 密文数据
   * @return 明文
   * @throws Exception 解密过程中的异常信息
   */
  public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)
    throws Exception {
    if (privateKey == null) {
      throw new Exception("解密私钥为空, 请设置");
    }
    Cipher cipher = null;
    try {
      // 使用默认RSA
      cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.DECRYPT_MODE, privateKey);
      // 密文的长度
      int inputLen = cipherData.length;
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      int offSet = 0;
      byte[] output;
      int i = 0;

      // 对数据分段解密
      while (inputLen - offSet > 0) {
        if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
          output = cipher.doFinal(cipherData, offSet, MAX_DECRYPT_BLOCK);
        } else {
          output = cipher.doFinal(cipherData, offSet, inputLen - offSet);
        }
        out.write(output, 0, output.length);
        i++;
        offSet = i * MAX_DECRYPT_BLOCK;
      }

      byte[] decryptedData = out.toByteArray();
      out.close();
      return decryptedData;
    } catch (NoSuchAlgorithmException e) {
      throw new Exception("无此解密算法");
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
      return null;
    } catch (InvalidKeyException e) {
      e.printStackTrace();
      throw new Exception("解密私钥非法,请检查");

    } catch (IllegalBlockSizeException e) {
      e.printStackTrace();
      throw new Exception("密文长度非法");
    } catch (BadPaddingException e) {
      e.printStackTrace();
      throw new Exception("密文数据已损坏");
    }
  }

  /**
   * 公钥解密过程
   * @param publicKey  公钥
   * @param cipherData 密文数据
   * @return 明文
   * @throws Exception 解密过程中的异常信息
   */
  public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)
    throws Exception {
    if (publicKey == null) {
      throw new Exception("解密公钥为空, 请设置");
    }
    Cipher cipher = null;
    try {
      // 使用默认RSA
      cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.DECRYPT_MODE, publicKey);

      // 密文的长度
      int inputLen = cipherData.length;
      ByteArrayOutputStream out = new ByteArrayOutputStream();

      int offSet = 0;
      byte[] output;
      int i = 0;

      // 对数据分段解密
      while (inputLen - offSet > 0) {
        if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
          output = cipher.doFinal(cipherData, offSet, MAX_DECRYPT_BLOCK);
        } else {
          output = cipher.doFinal(cipherData, offSet, inputLen - offSet);
        }
        out.write(output, 0, output.length);
        i++;
        offSet = i * MAX_DECRYPT_BLOCK;
      }

      byte[] decryptedData = out.toByteArray();
      out.close();
      return decryptedData;

    } catch (NoSuchAlgorithmException e) {
      throw new Exception("无此解密算法");
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
      return null;
    } catch (InvalidKeyException e) {
      throw new Exception("解密公钥非法,请检查");
    } catch (IllegalBlockSizeException e) {
      throw new Exception("密文长度非法");
    } catch (BadPaddingException e) {
      throw new Exception("密文数据已损坏");
    }
  }


  /**
   * 字节数据转十六进制字符串
   * @param data 输入数据
   * @return 十六进制内容
   */
  public static String byteArrayToString(byte[] data) {
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < data.length; i++) {
      // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
      stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
      // 取出字节的低四位 作为索引得到相应的十六进制标识符
      stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
      if (i < data.length - 1) {
        stringBuilder.append(' ');
      }
    }
    return stringBuilder.toString();
  }
}

第六步:三个加解密的通知类。

public class DecryptHttpInputMessage implements HttpInputMessage {
  private InputStream body;
  
  public DecryptHttpInputMessage(HttpInputMessage inputMessage, boolean showLog) throws Exception {

    String privatePath = 私钥证书的绝对地址;
    if (StringUtils.isEmpty(privatePath)) {
      throw new IllegalArgumentException("私钥为空");
    }
    String content = new BufferedReader(new InputStreamReader(inputMessage.getBody()))
      .lines().collect(Collectors.joining(System.lineSeparator()));
    String decryptBody;
    if (content.startsWith("{")) {
      logger.info("Unencrypted without decryption:{}", content);
      decryptBody = content;
    } else {
      content = content.replaceAll(" ", "+");

      // 私钥解密
      decryptBody = PrivateKeyUtils.decrypt(privatePath, content);
      logger.info("decryptBody=" + decryptBody);

      if (showLog) {
        logger.info("Encrypted data received:{},After decryption:{}", content, decryptBody);
      }
    }
    this.body = new ByteArrayInputStream(decryptBody.getBytes()); 	
  }

  @Override
  public InputStream getBody() {
    return body;
  }

  @Override
  public HttpHeaders getHeaders() {
    return headers;
  }
}
@ControllerAdvice
public class DecryptRequestBodyAdvice implements RequestBodyAdvice {

  // 是否使用"解密"注解
  private boolean encrypt;

  @Override
  public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {

    // 判断方法 是否使用"解密"注解
    if (methodParameter.getMethod().isAnnotationPresent(Decrypt.class)) {
      encrypt = true;
    }
    return encrypt;
  }
  
  @Override
  public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
    return body;
  }

  @Override
  public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,


                                         Class<? extends HttpMessageConverter<?>> converterType){
    if (encrypt) {

      logger.info("--START--");
      logger.info("-DecryptRequestBodyAdvice-");

      try {
        return new DecryptHttpInputMessage(inputMessage,false);
      } catch (Exception e) {
        e.printStackTrace();
        logger.error("Decryption failed", e);
      }
    }
    return inputMessage;
  }

  @Override
  public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
                              Class<? extends HttpMessageConverter<?>> converterType) {
    return body;
  }
}
@ControllerAdvice
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice<Object> {

  @Autowired
  private BocommMerchantService bocommMerchantService;

  // 是否使用"加密"注解
  private boolean encrypt;

  private static ThreadLocal<Boolean> encryptLocal = new ThreadLocal<>();

  @Override
  public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {

    // 判断方法 是否使用"加密"注解
    if (returnType.getMethod().isAnnotationPresent(Encrypt.class)) {
      encrypt = true;
    }
    return encrypt;
  }

  @Override
  public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    Boolean status = encryptLocal.get();

    if (null != status && !status) {
      encryptLocal.remove();
      return body;
    }

    if (encrypt) {
      try {
        String publicPath = 公钥证书的绝对路径;
        if (StringUtils.isEmpty(publicPath)){
          throw new IllegalArgumentException("公钥为空");
        }
        // 响应数据转成JSON字符串
        String content = JSON.toJSONString(body);

        //公钥加密
        String result = PublicKeyUtils.encrypt(publicPath, content);

        return result;
      } catch (Exception e) {
        throw new CustomException(e.getMessage(), 11);
      }
    }
    return body;
  }
}

第七步:在需要加解密的方法或接口根据需求上添加@Decrypt和@Encrypt注解即可。