【java】前端RSA加密后端解密
时间:2025-06-24 12:39:25 来源:新华社
【字体:  

目录

          • 1. 说明
          • 2. 前端示例
          • 3. 后端示例
            • 3.1 pom依赖
            • 3.2 后端结构图
            • 3.3 DecryptHttpInputMessage
            • 3.4 ApiCryptoProperties
            • 3.5 TestController
            • 3.6 ApiCryptoUtil
            • 3.7 ApiDecryptParamResolver
            • 3.8 ApiDecryptRequestBodyAdvice
            • 3.9 ApiDecryptRsa
            • 3.10 ApiCryptoProperties
            • 3.11 KeyPair
            • 3.12 Pair
            • 3.13 ClassUtil
            • 3.14 Func
            • 3.15 RsaUtil
            • 3.16 SpringBootLearningApplication启动类
            • 3.17 配置文件
          • 4. 调用截图

1. 说明
  • 1.RSA是非对称加密。
  • 2.前端采用公钥加密,后端采用私钥解密。
  • 3.此示例是前端加密,后端解密,后端返回的数据未加密。如果后端相应数据也要加密,可以另写注解,采用对称加密。
  • 4.公钥私钥的base64格式可以由RsaUtil工具类生成,参考其中main方法。
  • 5.在需要加密的接口上添加自定义注解@ApiDecryptRsa即可解密。
  • 5.ApiDecryptParamResolver是解析requestParam参数的,这里没写全,需要额外写注解。
2. 前端示例
  • 1.rsa依赖包
npm install jsencrypt
  • 2.页面代码
  • 3.api请求
import request from "@/axios";export const save = row => {   return request({     url: '/xapi/test/save',    headers: {       'Content-Type': 'text/plain'    },    method: 'post',    data: row,  });};
3. 后端示例
3.1 pom依赖
  • 1.pom依赖
    4.0.0    org.example    my-springboot    1.0-SNAPSHOT            8        8                org.springframework.boot        spring-boot-starter-parent        2.7.6                            org.springframework.boot            spring-boot-starter-web                            org.springframework.boot            spring-boot-autoconfigure                            org.springframework            spring-core                            com.alibaba            fastjson            2.0.40                            com.fasterxml.jackson.core            jackson-databind            2.13.0                            org.projectlombok            lombok                            org.springframework.boot            spring-boot-autoconfigure            
3.2 后端结构图
  • 2.后端结构图
    在这里插入图片描述
3.3 DecryptHttpInputMessage
  • 3.DecryptHttpInputMessage
package com.learning.bean;import lombok.Getter;import lombok.RequiredArgsConstructor;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpInputMessage;import java.io.InputStream;/** * 

解密信息输入流

* */@Getter@RequiredArgsConstructorpublic class DecryptHttpInputMessage implements HttpInputMessage { private final InputStream body; private final HttpHeaders headers;}
3.4 ApiCryptoProperties
  • 4.ApiCryptoProperties
package com.learning.config;import com.learning.crypto.advice.ApiDecryptParamResolver;import com.learning.crypto.props.ApiCryptoProperties;import lombok.RequiredArgsConstructor;import org.springframework.boot.autoconfigure.AutoConfiguration;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.web.method.support.HandlerMethodArgumentResolver;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;/** * api 签名自动配置 * */@AutoConfiguration@RequiredArgsConstructor@EnableConfigurationProperties(ApiCryptoProperties.class)@ConditionalOnProperty(value = ApiCryptoProperties.PREFIX + ".enabled", havingValue = "true", matchIfMissing = true)public class ApiCryptoConfiguration implements WebMvcConfigurer { 	private final ApiCryptoProperties apiCryptoProperties;	@Override	public void addArgumentResolvers(List argumentResolvers) { 		argumentResolvers.add(new ApiDecryptParamResolver(apiCryptoProperties));	}}
3.5 TestController
  • 5.TestController
package com.learning.controller;import com.learning.crypto.annotation.ApiDecryptRsa;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/test")public class TestController {     @PostMapping(value = "/save", produces = "text/plain")    @ApiDecryptRsa    public String save(@RequestBody String data){         return data;    }}
3.6 ApiCryptoUtil
  • 6.ApiCryptoUtil
package com.learning.crypto.advice;import com.learning.crypto.props.ApiCryptoProperties;import java.util.Objects;import com.learning.util.RsaUtil;/** * 

辅助工具类

* */public class ApiCryptoUtil { /** * 选择加密方式并进行解密 * * @param bodyData byte array * @return 解密结果 */ public static byte[] decryptData(ApiCryptoProperties properties, byte[] bodyData) { String privateKey = Objects.requireNonNull(properties.getRsaPrivateKey()); return RsaUtil.decryptFromBase64(privateKey, bodyData); }}
3.7 ApiDecryptParamResolver
  • 7.ApiDecryptParamResolver
package com.learning.crypto.advice;import com.fasterxml.jackson.databind.ObjectMapper;import com.learning.crypto.annotation.ApiDecryptRsa;import com.learning.crypto.props.ApiCryptoProperties;import com.learning.util.Func;import lombok.RequiredArgsConstructor;import org.springframework.core.MethodParameter;import org.springframework.core.annotation.AnnotatedElementUtils;import org.springframework.lang.Nullable;import org.springframework.web.bind.support.WebDataBinderFactory;import org.springframework.web.context.request.NativeWebRequest;import org.springframework.web.method.support.HandlerMethodArgumentResolver;import org.springframework.web.method.support.ModelAndViewContainer;import java.lang.reflect.Parameter;import java.nio.charset.StandardCharsets;/** * param 参数 解析 * */@RequiredArgsConstructorpublic class ApiDecryptParamResolver implements HandlerMethodArgumentResolver { 	private final ApiCryptoProperties properties;	@Override	public boolean supportsParameter(MethodParameter parameter) { 		return AnnotatedElementUtils.hasAnnotation(parameter.getParameter(), ApiDecryptRsa.class);	}	@Nullable	@Override	public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer mavContainer,								  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { 		Parameter parameter = methodParameter.getParameter();		String text = webRequest.getParameter(properties.getParamName());		if (Func.isEmpty(text)) { 			return null;		}		byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);		byte[] decryptData = ApiCryptoUtil.decryptData(properties, textBytes);		ObjectMapper mapper = new ObjectMapper();		try{ 			return mapper.readValue(decryptData, parameter.getType());		}catch (Exception e){ 			e.printStackTrace();			return null;		}	}}
3.8 ApiDecryptRequestBodyAdvice
  • 8.ApiDecryptRequestBodyAdvice
package com.learning.crypto.advice;import com.learning.crypto.annotation.ApiDecryptRsa;import com.learning.crypto.props.ApiCryptoProperties;import com.learning.util.ClassUtil;import com.learning.bean.DecryptHttpInputMessage;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.autoconfigure.AutoConfiguration;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.core.MethodParameter;import org.springframework.core.annotation.Order;import org.springframework.http.HttpInputMessage;import org.springframework.http.converter.HttpMessageConverter;import org.springframework.lang.NonNull;import org.springframework.util.StreamUtils;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Type;/** * 请求数据的加密信息解密处理
* 本类只对控制器参数中含有{ @link org.springframework.web.bind.annotation.RequestBody} * 以及package为ccom.xiaoi.xics.core.crypto.api.signature.annotation.decrypt下的注解有效 */@Slf4j@Order(1)@AutoConfiguration@ControllerAdvice@RequiredArgsConstructor@ConditionalOnProperty(value = ApiCryptoProperties.PREFIX + ".enabled", havingValue = "true", matchIfMissing = true)public class ApiDecryptRequestBodyAdvice implements RequestBodyAdvice { private final ApiCryptoProperties properties; @Override public boolean supports(MethodParameter methodParameter, @NonNull Type targetType, @NonNull Class> converterType) { return ClassUtil.isAnnotated(methodParameter.getMethod(), ApiDecryptRsa.class); } @Override public Object handleEmptyBody(Object body, @NonNull HttpInputMessage inputMessage, @NonNull MethodParameter parameter, @NonNull Type targetType, @NonNull Class> converterType) { return body; } @NonNull @Override public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, @NonNull MethodParameter parameter, @NonNull Type targetType, @NonNull Class> converterType) throws IOException { // 判断 body 是否为空 InputStream messageBody = inputMessage.getBody(); if (messageBody.available() <= 0) { return inputMessage; } byte[] decryptedBody = null; byte[] bodyByteArray = StreamUtils.copyToByteArray(messageBody); decryptedBody = ApiCryptoUtil.decryptData(properties, bodyByteArray); if (decryptedBody == null) { throw new RuntimeException("Decryption error, " + "please check if the selected source data is encrypted correctly." + " (解密错误,请检查选择的源数据的加密方式是否正确。)"); } InputStream inputStream = new ByteArrayInputStream(decryptedBody); return new DecryptHttpInputMessage(inputStream, inputMessage.getHeaders()); } @NonNull @Override public Object afterBodyRead(@NonNull Object body, @NonNull HttpInputMessage inputMessage, @NonNull MethodParameter parameter, @NonNull Type targetType, @NonNull Class> converterType) { return body; }}
3.9 ApiDecryptRsa
  • 9.ApiDecryptRsa
package com.learning.crypto.annotation;import java.lang.annotation.*;/** * rsa 解密 */@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)@Documented@Inheritedpublic @interface ApiDecryptRsa { }
3.10 ApiCryptoProperties
  • 10.ApiCryptoProperties
package com.learning.crypto.props;import lombok.Getter;import lombok.Setter;import org.springframework.boot.context.properties.ConfigurationProperties;/** * api 签名配置类 */@Getter@Setter@ConfigurationProperties(ApiCryptoProperties.PREFIX)public class ApiCryptoProperties { 	/**	 * 前缀	 */	public static final String PREFIX = "api.crypto";	/**	 * 是否开启 api 签名	 */	private Boolean enabled = Boolean.TRUE;	/**	 * url的参数签名,传递的参数名。例如:/user?data=签名后的数据	 */	private String paramName = "data";	/**	 * rsa 私钥	 */	private String rsaPrivateKey;}
3.11 KeyPair
  • 11.KeyPair
package com.learning.crypto.tuple;import com.learning.util.RsaUtil;import lombok.RequiredArgsConstructor;import java.security.PrivateKey;import java.security.PublicKey;/** * rsa 的 key pair 封装 * */@RequiredArgsConstructorpublic class KeyPair { 	private final java.security.KeyPair keyPair;	public PublicKey getPublic() { 		return keyPair.getPublic();	}	public PrivateKey getPrivate() { 		return keyPair.getPrivate();	}	public byte[] getPublicBytes() { 		return this.getPublic().getEncoded();	}	public byte[] getPrivateBytes() { 		return this.getPrivate().getEncoded();	}	public String getPublicBase64() { 		return RsaUtil.getKeyString(this.getPublic());	}	public String getPrivateBase64() { 		return RsaUtil.getKeyString(this.getPrivate());	}	@Override	public String toString() { 		return "PublicKey=" + this.getPublicBase64() + '\n' + "PrivateKey=" + this.getPrivateBase64();	}}
3.12 Pair
  • 12.Pair
package com.learning.crypto.tuple;import lombok.EqualsAndHashCode;import lombok.Getter;import lombok.ToString;/** * tuple Pair **/@Getter@ToString@EqualsAndHashCodepublic class Pair { 	private static final Pair EMPTY = new Pair<>(null, null);	private final L left;	private final R right;	/**	 * Returns an empty pair.	 */	@SuppressWarnings("unchecked")	public static  Pair empty() { 		return (Pair) EMPTY;	}	/**	 * Constructs a pair with its left value being { @code left}, or returns an empty pair if	 * { @code left} is null.	 *	 * @return the constructed pair or an empty pair if { @code left} is null.	 */	public static  Pair createLeft(L left) { 		if (left == null) { 			return empty();		} else { 			return new Pair<>(left, null);		}	}	/**	 * Constructs a pair with its right value being { @code right}, or returns an empty pair if	 * { @code right} is null.	 *	 * @return the constructed pair or an empty pair if { @code right} is null.	 */	public static  Pair createRight(R right) { 		if (right == null) { 			return empty();		} else { 			return new Pair<>(null, right);		}	}	public static  Pair create(L left, R right) { 		if (right == null && left == null) { 			return empty();		} else { 			return new Pair<>(left, right);		}	}	private Pair(L left, R right) { 		this.left = left;		this.right = right;	}}
3.13 ClassUtil
  • 13.ClassUtil
package com.learning.util;import org.springframework.core.BridgeMethodResolver;import org.springframework.core.DefaultParameterNameDiscoverer;import org.springframework.core.MethodParameter;import org.springframework.core.ParameterNameDiscoverer;import org.springframework.core.annotation.AnnotatedElementUtils;import org.springframework.core.annotation.SynthesizingMethodParameter;import org.springframework.web.method.HandlerMethod;import java.lang.annotation.Annotation;import java.lang.reflect.Constructor;import java.lang.reflect.Method;/** * 类操作工具 */public class ClassUtil extends org.springframework.util.ClassUtils { 	private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();	/**	 * 获取方法参数信息	 *	 * @param constructor    构造器	 * @param parameterIndex 参数序号	 * @return { MethodParameter}	 */	public static MethodParameter getMethodParameter(Constructor constructor, int parameterIndex) { 		MethodParameter methodParameter = new SynthesizingMethodParameter(constructor, parameterIndex);		methodParameter.initParameterNameDiscovery(PARAMETER_NAME_DISCOVERER);		return methodParameter;	}	/**	 * 获取方法参数信息	 *	 * @param method         方法	 * @param parameterIndex 参数序号	 * @return { MethodParameter}	 */	public static MethodParameter getMethodParameter(Method method, int parameterIndex) { 		MethodParameter methodParameter = new SynthesizingMethodParameter(method, parameterIndex);		methodParameter.initParameterNameDiscovery(PARAMETER_NAME_DISCOVERER);		return methodParameter;	}	/**	 * 获取Annotation	 *	 * @param method         Method	 * @param annotationType 注解类	 * @param             泛型标记	 * @return { Annotation}	 */	public static  A getAnnotation(Method method, Class annotationType) { 		Class targetClass = method.getDeclaringClass();		// The method may be on an interface, but we need attributes from the target class.		// If the target class is null, the method will be unchanged.		Method specificMethod = ClassUtil.getMostSpecificMethod(method, targetClass);		// If we are dealing with method with generic parameters, find the original method.		specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);		// 先找方法,再找方法上的类		A annotation = AnnotatedElementUtils.findMergedAnnotation(specificMethod, annotationType);		;		if (null != annotation) { 			return annotation;		}		// 获取类上面的Annotation,可能包含组合注解,故采用spring的工具类		return AnnotatedElementUtils.findMergedAnnotation(specificMethod.getDeclaringClass(), annotationType);	}	/**	 * 获取Annotation	 *	 * @param handlerMethod  HandlerMethod	 * @param annotationType 注解类	 * @param             泛型标记	 * @return { Annotation}	 */	public static  A getAnnotation(HandlerMethod handlerMethod, Class annotationType) { 		// 先找方法,再找方法上的类		A annotation = handlerMethod.getMethodAnnotation(annotationType);		if (null != annotation) { 			return annotation;		}		// 获取类上面的Annotation,可能包含组合注解,故采用spring的工具类		Class beanType = handlerMethod.getBeanType();		return AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType);	}	/**	 * 判断是否有注解 Annotation	 *	 * @param method         Method	 * @param annotationType 注解类	 * @param             泛型标记	 * @return { boolean}	 */	public static  boolean isAnnotated(Method method, Class annotationType) { 		// 先找方法,再找方法上的类		boolean isMethodAnnotated = AnnotatedElementUtils.isAnnotated(method, annotationType);		if (isMethodAnnotated) { 			return true;		}		// 获取类上面的Annotation,可能包含组合注解,故采用spring的工具类		Class targetClass = method.getDeclaringClass();		return AnnotatedElementUtils.isAnnotated(targetClass, annotationType);	}}
3.14 Func
package com.learning.util;import org.springframework.lang.Nullable;import org.springframework.util.ObjectUtils;/** * 工具类 */public class Func { 	/**	 * 判断空对象 object、map、list、set、字符串、数组	 *	 * @param obj the object to check	 * @return 数组是否为空	 */	public static boolean isEmpty(@Nullable Object obj) { 		return ObjectUtils.isEmpty(obj);	}	/**	 * 对象不为空 object、map、list、set、字符串、数组	 *	 * @param obj the object to check	 * @return 是否不为空	 */	public static boolean isNotEmpty(@Nullable Object obj) { 		return !ObjectUtils.isEmpty(obj);	}}
3.15 RsaUtil
package com.learning.util;import com.learning.crypto.tuple.KeyPair;import org.springframework.lang.Nullable;import org.springframework.util.Base64Utils;import javax.crypto.Cipher;import java.math.BigInteger;import java.nio.charset.StandardCharsets;import java.security.*;import java.security.spec.*;import java.util.Objects;/** * RSA加、解密工具 * * 1. 公钥负责加密,私钥负责解密; * 2. 私钥负责签名,公钥负责验证。 */public class RsaUtil { 	/**	 * 数字签名,密钥算法	 */	public static final String RSA_ALGORITHM = "RSA";	public static final String RSA_PADDING = "RSA/ECB/PKCS1Padding";	/**	 * 获取 KeyPair	 *	 * @return KeyPair	 */	public static KeyPair genKeyPair() { 		return genKeyPair(1024);	}	/**	 * 获取 KeyPair	 *	 * @param keySize key size	 * @return KeyPair	 */	public static KeyPair genKeyPair(int keySize) { 		try { 			KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA_ALGORITHM);			// 密钥位数			keyPairGen.initialize(keySize);			// 密钥对			return new KeyPair(keyPairGen.generateKeyPair());		} catch (Exception e) { 			throw new RuntimeException(e);		}	}	/**	 * 生成RSA私钥	 *	 * @param modulus N特征值	 * @param exponent d特征值	 * @return { @link PrivateKey}	 */	public static PrivateKey generatePrivateKey(String modulus, String exponent) { 		return generatePrivateKey(new BigInteger(modulus), new BigInteger(exponent));	}	/**	 * 生成RSA私钥	 *	 * @param modulus N特征值	 * @param exponent d特征值	 * @return { @link PrivateKey}	 */	public static PrivateKey generatePrivateKey(BigInteger modulus, BigInteger exponent) { 		RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(modulus, exponent);		try { 			KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);			return keyFactory.generatePrivate(keySpec);		} catch (Exception e) { 			throw new RuntimeException(e);		}	}	/**	 * 生成RSA公钥	 *	 * @param modulus N特征值	 * @param exponent e特征值	 * @return { @link PublicKey}	 */	public static PublicKey generatePublicKey(String modulus, String exponent) { 		return generatePublicKey(new BigInteger(modulus), new BigInteger(exponent));	}	/**	 * 生成RSA公钥	 *	 * @param modulus N特征值	 * @param exponent e特征值	 * @return { @link PublicKey}	 */	public static PublicKey generatePublicKey(BigInteger modulus, BigInteger exponent) { 		RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);		try { 			KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);			return keyFactory.generatePublic(keySpec);		} catch (Exception e) { 			throw new RuntimeException(e);		}	}	/**	 * 得到公钥	 *	 * @param base64PubKey 密钥字符串(经过base64编码)	 * @return PublicKey	 */	public static PublicKey getPublicKey(String base64PubKey) { 		Objects.requireNonNull(base64PubKey, "base64 public key is null.");		byte[] keyBytes = Base64Utils.decodeFromString(base64PubKey);		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);		try { 			KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);			return keyFactory.generatePublic(keySpec);		} catch (Exception e) { 			throw new RuntimeException(e);		}	}	/**	 * 得到公钥字符串	 *	 * @param base64PubKey 密钥字符串(经过base64编码)	 * @return PublicKey String	 */	public static String getPublicKeyToBase64(String base64PubKey) { 		PublicKey publicKey = getPublicKey(base64PubKey);		return getKeyString(publicKey);	}	/**	 * 得到私钥	 *	 * @param base64PriKey 密钥字符串(经过base64编码)	 * @return PrivateKey	 */	public static PrivateKey getPrivateKey(String base64PriKey) { 		Objects.requireNonNull(base64PriKey, "base64 private key is null.");		byte[] keyBytes = Base64Utils.decodeFromString(base64PriKey);		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);		try { 			KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);			return keyFactory.generatePrivate(keySpec);		} catch (NoSuchAlgorithmException | InvalidKeySpecException e) { 			throw new RuntimeException(e);		}	}	/**	 * 得到密钥字符串(经过base64编码)	 *	 * @param key key	 * @return base 64 编码后的 key	 */	public static String getKeyString(Key key) { 		return Base64Utils.encodeToString(key.getEncoded());	}	/**	 * 得到私钥 base64	 *	 * @param base64PriKey 密钥字符串(经过base64编码)	 * @return PrivateKey String	 */	public static String getPrivateKeyToBase64(String base64PriKey) { 		PrivateKey privateKey = getPrivateKey(base64PriKey);		return getKeyString(privateKey);	}	/**	 * 共要加密	 *	 * @param base64PublicKey base64 的公钥	 * @param data            待加密的内容	 * @return 加密后的内容	 */	public static byte[] encrypt(String base64PublicKey, byte[] data) { 		return encrypt(getPublicKey(base64PublicKey), data);	}	/**	 * 共要加密	 *	 * @param publicKey 公钥	 * @param data      待加密的内容	 * @return 加密后的内容	 */	public static byte[] encrypt(PublicKey publicKey, byte[] data) { 		return rsa(publicKey, data, Cipher.ENCRYPT_MODE);	}	/**	 * 私钥加密,用于 qpp 内,公钥解密	 *	 * @param base64PrivateKey base64 的私钥	 * @param data             待加密的内容	 * @return 加密后的内容	 */	public static byte[] encryptByPrivateKey(String base64PrivateKey, byte[] data) { 		return encryptByPrivateKey(getPrivateKey(base64PrivateKey), data);	}	/**	 * 私钥加密,加密成 base64 字符串,用于 qpp 内,公钥解密	 *	 * @param base64PrivateKey base64 的私钥	 * @param data             待加密的内容	 * @return 加密后的内容	 */	public static String encryptByPrivateKeyToBase64(String base64PrivateKey, byte[] data) { 		return Base64Utils.encodeToString(encryptByPrivateKey(base64PrivateKey, data));	}	/**	 * 私钥加密,用于 qpp 内,公钥解密	 *	 * @param privateKey 私钥	 * @param data       待加密的内容	 * @return 加密后的内容	 */	public static byte[] encryptByPrivateKey(PrivateKey privateKey, byte[] data) { 		return rsa(privateKey, data, Cipher.ENCRYPT_MODE);	}	/**	 * 公钥加密	 *	 * @param base64PublicKey base64 公钥	 * @param data            待加密的内容	 * @return 加密后的内容	 */	@Nullable	public static String encryptToBase64(String base64PublicKey, @Nullable String data) { 		if (Func.isEmpty(data)) { 			return null;		}		return Base64Utils.encodeToString(encrypt(base64PublicKey, data.getBytes(StandardCharsets.UTF_8)));	}	/**	 * 解密	 *	 * @param base64PrivateKey base64 私钥	 * @param data             数据	 * @return 解密后的数据	 */	public static byte[] decrypt(String base64PrivateKey, byte[] data) { 		return decrypt(getPrivateKey(base64PrivateKey), data);	}	/**	 * 解密	 *	 * @param base64publicKey base64 公钥	 * @param data            数据	 * @return 解密后的数据	 */	public static byte[] decryptByPublicKey(String base64publicKey, byte[] data) { 		return decryptByPublicKey(getPublicKey(base64publicKey), data);	}	/**	 * 解密	 *	 * @param privateKey privateKey	 * @param data       数据	 * @return 解密后的数据	 */	public static byte[] decrypt(PrivateKey privateKey, byte[] data) { 		return rsa(privateKey, data, Cipher.DECRYPT_MODE);	}	/**	 * 解密	 *	 * @param publicKey PublicKey	 * @param data      数据	 * @return 解密后的数据	 */	public static byte[] decryptByPublicKey(PublicKey publicKey, byte[] data) { 		return rsa(publicKey, data, Cipher.DECRYPT_MODE);	}	/**	 * rsa 加、解密	 *	 * @param key  key	 * @param data 数据	 * @param mode 模式	 * @return 解密后的数据	 */	private static byte[] rsa(Key key, byte[] data, int mode) { 		try { 			Cipher cipher = Cipher.getInstance(RSA_PADDING);			cipher.init(mode, key);			return cipher.doFinal(data);		} catch (Exception e) { 			throw new RuntimeException(e);		}	}	/**	 * base64 数据解密	 *	 * @param base64PublicKey base64 公钥	 * @param base64Data      base64数据	 * @return 解密后的数据	 */	public static byte[] decryptByPublicKeyFromBase64(String base64PublicKey, byte[] base64Data) { 		return decryptByPublicKey(getPublicKey(base64PublicKey), base64Data);	}	/**	 * base64 数据解密	 *	 * @param base64PrivateKey base64 私钥	 * @param base64Data       base64数据	 * @return 解密后的数据	 */	@Nullable	public static String decryptFromBase64(String base64PrivateKey, @Nullable String base64Data) { 		if (Func.isEmpty(base64Data)) { 			return null;		}		return new String(decrypt(base64PrivateKey, Base64Utils.decodeFromString(base64Data)), StandardCharsets.UTF_8);	}	/**	 * base64 数据解密	 *	 * @param base64PrivateKey base64 私钥	 * @param base64Data       base64数据	 * @return 解密后的数据	 */	public static byte[] decryptFromBase64(String base64PrivateKey, byte[] base64Data) { 		return decrypt(base64PrivateKey, Base64Utils.decode(base64Data));	}	/**	 * base64 数据解密	 *	 * @param base64PublicKey base64 公钥	 * @param base64Data      base64数据	 * @return 解密后的数据	 */	@Nullable	public static String decryptByPublicKeyFromBase64(String base64PublicKey, @Nullable String base64Data) { 		if (Func.isEmpty(base64Data)) { 			return null;		}		return new String(decryptByPublicKeyFromBase64(base64PublicKey, Base64Utils.decodeFromString(base64Data)), StandardCharsets.UTF_8);	}	public static void main(String[] args) { //		KeyPair keyPair = genKeyPair();//		System.out.println("私钥:"+keyPair.getPrivateBase64());//		System.out.println("公钥:"+keyPair.getPublicBase64());		String privateBase64 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAImWaSqyYDbyu39uwEnaEMR29siUS+cnZ+DSCbX76tfFc0QG8bIKfCcPG/O2Owe1uii0B14HUPvcNV8IrMKPkt79a/bWWW+uIbVsB4zfNITLA8pDNb/nOELcE4N3Hy+4V7evUrG6ep1ceb/ru2cL9UxLzlca0IGRx8BcIlnI0TmtAgMBAAECgYBFSLLIx25f/Teh4jl+dws+g9GeC991FYjf06UEOUl3Qnza4sxPJayDVr5yqW9sYHzQBmg3V2PWkHtn0cx9ZSNF3iyDd0EQOb0ky9M7qWXifCD0uG1Ruc+cb1/vewRrj15VH2qOd9jmgeZhxWelvx0cENRpEMicIJ+zTt0kvX+UQQJBAMECqoBG5A5X3lkSdgsUbLtNbeIsPqH+FLA3+3UT29u+s5b9uPXhWBwVfRt3gtgJxaftiI/LHA7WZbFUYrKcxGUCQQC2fVxhNSFwTeiRCoimx+WID3fILOBNPNzGr75YzOzJdDpdnvHElo2CsUatoGDSk8S2hcUtwI2LSm/yxX9bzJepAkEAg/fYsIDIKe52fxyaTZUXizGz8jMiWAysBJkie7iqWSOZE6JDtwru/bTLp94dPq3f0aQd/YN4mcSKH6d9HHcH6QJAZrDOnkj2oyrEN3I1CZ0tNc52eid+pRgdqJTWyUOv74E/ItXBeP27bhLyEdxQ/851gLxwA9n6DKr7qiKnE3Ji2QJAMcs1ipl0n/aR0NR56/uI0R1cD2AsoimfZjc8hPWdjs/YfpZVQnrcpgQx5Ps4O631F7LQKz22MbwOoBt3UcZYSQ==";		String publicBase64 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJlmkqsmA28rt/bsBJ2hDEdvbIlEvnJ2fg0gm1++rXxXNEBvGyCnwnDxvztjsHtbootAdeB1D73DVfCKzCj5Le/Wv21llvriG1bAeM3zSEywPKQzW/5zhC3BODdx8vuFe3r1KxunqdXHm/67tnC/VMS85XGtCBkcfAXCJZyNE5rQIDAQAB";		System.out.println("加密数据:"+encryptToBase64(publicBase64, "hello world"));		System.out.println("解密数据:"+decryptFromBase64(privateBase64, encryptToBase64(publicBase64, "hello world")));		String data = "hu5u8UyEg6fcn+/4wKFRSUVGETrXGifVE6/RzRBQCVxAQt+XMA7C+xVR6Ws2ZXFmYVFoS0YL29u6oVkxvmESdRc9Zj/bf0M6ykqa57vyvvRRmrrqCSYUD6STo/QRdPFK4sxlsseTU2/XjZQYohnrMmouYspWykJ3fcN34uoieHc=";//		System.out.println("解密数据:"+decryptFromBase64(privateBase64, data));		System.out.println("解密数据:"+RsaUtil.decryptFromBase64(privateBase64, data));	}}
3.16 SpringBootLearningApplication启动类
package com.learning;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.ComponentScan;/** **/@SpringBootApplication@ComponentScan(basePackages = { "com.learning"})public class SpringBootLearningApplication {     public static void main(String[] args) {         SpringApplication.run(SpringBootLearningApplication.class, args);    }}
3.17 配置文件
api:  crypto:    # 私钥    rsaPrivateKey: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAImWaSqyYDbyu39uwEnaEMR29siUS+cnZ+DSCbX76tfFc0QG8bIKfCcPG/O2Owe1uii0B14HUPvcNV8IrMKPkt79a/bWWW+uIbVsB4zfNITLA8pDNb/nOELcE4N3Hy+4V7evUrG6ep1ceb/ru2cL9UxLzlca0IGRx8BcIlnI0TmtAgMBAAECgYBFSLLIx25f/Teh4jl+dws+g9GeC991FYjf06UEOUl3Qnza4sxPJayDVr5yqW9sYHzQBmg3V2PWkHtn0cx9ZSNF3iyDd0EQOb0ky9M7qWXifCD0uG1Ruc+cb1/vewRrj15VH2qOd9jmgeZhxWelvx0cENRpEMicIJ+zTt0kvX+UQQJBAMECqoBG5A5X3lkSdgsUbLtNbeIsPqH+FLA3+3UT29u+s5b9uPXhWBwVfRt3gtgJxaftiI/LHA7WZbFUYrKcxGUCQQC2fVxhNSFwTeiRCoimx+WID3fILOBNPNzGr75YzOzJdDpdnvHElo2CsUatoGDSk8S2hcUtwI2LSm/yxX9bzJepAkEAg/fYsIDIKe52fxyaTZUXizGz8jMiWAysBJkie7iqWSOZE6JDtwru/bTLp94dPq3f0aQd/YN4mcSKH6d9HHcH6QJAZrDOnkj2oyrEN3I1CZ0tNc52eid+pRgdqJTWyUOv74E/ItXBeP27bhLyEdxQ/851gLxwA9n6DKr7qiKnE3Ji2QJAMcs1ipl0n/aR0NR56/uI0R1cD2AsoimfZjc8hPWdjs/YfpZVQnrcpgQx5Ps4O631F7LQKz22MbwOoBt3UcZYSQ==
4. 调用截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

[责任编辑:百度一下]
检察日报数字报 | 正义网 |
Copyrights©最高人民检察院 All Rights Reserved.