【java】前端RSA加密后端解密

目录

          • 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.页面代码
<template><el-button type="primary" icon="el-icon-plus" @click="handleTest">测试</el-button>
</template><script>
import { save } from "@/api/test";
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min';
export default {name: '测试RSA加密',methods: {handleTest(){const crypt = new JSEncrypt()// 公钥,由后端接口返回,这里写死作为测试const publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJlmkqsmA28rt/bsBJ2hDEdvbIlEvnJ2fg0gm1++rXxXNEBvGyCnwnDxvztjsHtbootAdeB1D73DVfCKzCj5Le/Wv21llvriG1bAeM3zSEywPKQzW/5zhC3BODdx8vuFe3r1KxunqdXHm/67tnC/VMS85XGtCBkcfAXCJZyNE5rQIDAQAB';crypt.setPublicKey(publicKey)const data = {"content": "测试",}const encrypted = crypt.encrypt(JSON.stringify(data))console.log(encrypted)// 调用接口save(encrypted).then(res=>{console.log(res.data)})},}
}
</script>
  • 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依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>my-springboot</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.6</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.40</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency></dependencies>
</project>
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;/*** <p>解密信息输入流</p>**/
@Getter
@RequiredArgsConstructor
public 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;@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> 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")@ApiDecryptRsapublic 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;
/*** <p>辅助工具类</p>**/
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 参数 解析**/
@RequiredArgsConstructor
public class ApiDecryptParamResolver implements HandlerMethodArgumentResolver {private final ApiCryptoProperties properties;@Overridepublic boolean supportsParameter(MethodParameter parameter) {return AnnotatedElementUtils.hasAnnotation(parameter.getParameter(), ApiDecryptRsa.class);}@Nullable@Overridepublic 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;/*** 请求数据的加密信息解密处理<br>* 本类只对控制器参数中含有<strong>{@link org.springframework.web.bind.annotation.RequestBody}</strong>* 以及package为<strong><code>ccom.xiaoi.xics.core.crypto.api.signature.annotation.decrypt</code></strong>下的注解有效*/
@Slf4j
@Order(1)
@AutoConfiguration
@ControllerAdvice
@RequiredArgsConstructor
@ConditionalOnProperty(value = ApiCryptoProperties.PREFIX + ".enabled", havingValue = "true", matchIfMissing = true)
public class ApiDecryptRequestBodyAdvice implements RequestBodyAdvice {private final ApiCryptoProperties properties;@Overridepublic boolean supports(MethodParameter methodParameter, @NonNull Type targetType, @NonNull Class<? extends HttpMessageConverter<?>> converterType) {return ClassUtil.isAnnotated(methodParameter.getMethod(), ApiDecryptRsa.class);}@Overridepublic Object handleEmptyBody(Object body, @NonNull HttpInputMessage inputMessage, @NonNull MethodParameter parameter, @NonNull Type targetType, @NonNull Class<? extends HttpMessageConverter<?>> converterType) {return body;}@NonNull@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, @NonNull MethodParameter parameter, @NonNull Type targetType, @NonNull Class<? extends HttpMessageConverter<?>> 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@Overridepublic Object afterBodyRead(@NonNull Object body, @NonNull HttpInputMessage inputMessage, @NonNull MethodParameter parameter, @NonNull Type targetType, @NonNull Class<? extends HttpMessageConverter<?>> 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
@Inherited
public @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 封装**/
@RequiredArgsConstructor
public 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());}@Overridepublic 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
@EqualsAndHashCode
public class Pair<L, R> {private static final Pair<Object, Object> EMPTY = new Pair<>(null, null);private final L left;private final R right;/*** Returns an empty pair.*/@SuppressWarnings("unchecked")public static <L, R> Pair<L, R> empty() {return (Pair<L, R>) 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 <L, R> Pair<L, R> 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 <L, R> Pair<L, R> createRight(R right) {if (right == null) {return empty();} else {return new Pair<>(null, right);}}public static <L, R> Pair<L, R> 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 <A>            泛型标记* @return {Annotation}*/public static <A extends Annotation> A getAnnotation(Method method, Class<A> 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 <A>            泛型标记* @return {Annotation}*/public static <A extends Annotation> A getAnnotation(HandlerMethod handlerMethod, Class<A> 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 <A>            泛型标记* @return {boolean}*/public static <A extends Annotation> boolean isAnnotated(Method method, Class<A> 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
  • 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
  • 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 加密后的内容*/@Nullablepublic 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 解密后的数据*/@Nullablepublic 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 解密后的数据*/@Nullablepublic 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启动类
  • 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 配置文件
  • 17.application.yaml
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. 调用截图

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/54865.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android界面控件概述

节选自《Android应用开发项目式教程》&#xff0c;机械工业出版社&#xff0c;2024年7月出版 做最简单的安卓入门教程&#xff0c;手把手视频、代码、答疑全配齐 控件是Android界面的重要组成单元&#xff0c;Android应用主要通过控件与用户交互&#xff0c;Android提供了非常…

raise Exception(“IPAdapter model not found.“)

IPAdapter模型文件太多了&#xff0c;而节点IPAdapter Unified Loader是通过函数&#xff08;get_ipadapter_file与get_clipvision_file&#xff09;预设来加载模型文件&#xff0c;当发生错误“IPAdapter model not found.“时并不指明模型文件名&#xff0c;导致想要有针对性…

在MacOS上安装MongoDB数据库

一、安装方法 1.1 安装包安装 首先&#xff0c;打开MongoDB 官网下载安装包&#xff0c;下载链接&#xff1a;https://www.mongodb.com/try/download/community。 根据自己的系统环境自行选择下载的版本。将下载好的 MongoDB 安装包解压缩&#xff0c;并将文件夹名改为 mon…

理解:基础地理实体相关概述

理解&#xff1a;基础地理实体相关概述 地理实体 geo-entity 现实世界中占据一定且连续空间位置和范围、单独具有同一属 性或完整功能的地理对象。 基础地理实体 fundamental geo-entity 通过基础测绘采集和表达的地理实体&#xff0c;是其他地理实体和相关 信息的定位框架与…

卡通角色检测系统源码分享

卡通角色检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

Keepalived+MySQL 高可用集群

基础架构如下 准备干净的实验环境 [rootmysql1 ~]# systemctl stop firewalld [rootmysql1 ~]# cat /etc/sysconfig/selinux |grep "SELINUXdisabled" SELINUXdisabled [rootmysql1 ~]# setenforce 0 setenforce: SELinux is disabled [rootmysql1 ~…

IoT网关的主要功能有哪些?天拓四方

在数字化浪潮席卷全球的今天&#xff0c;物联网&#xff08;IoT&#xff09;技术凭借其独特的优势&#xff0c;逐渐在各个领域展现出强大的生命力。而IoT网关&#xff0c;作为连接物理世界与数字世界的桥梁&#xff0c;其在物联网体系中的作用愈发凸显。 一、数据聚合与预处理…

acw(树的重心)

给定一颗树&#xff0c;树中包含 n&#x1d45b; 个结点&#xff08;编号 1∼n1∼&#x1d45b;&#xff09;和 n−1&#x1d45b;−1 条无向边。 请你找到树的重心&#xff0c;并输出将重心删除后&#xff0c;剩余各个连通块中点数的最大值。 重心定义&#xff1a;重心是指树…

《论文阅读》 用于产生移情反应的迭代联想记忆模型 ACL2024

《论文阅读》 用于产生移情反应的迭代联想记忆模型 ACL2024 前言简介任务定义模型架构Encoding Dialogue InformationCapturing Associated InformationPredicting Emotion and Generating Response损失函数问题前言 亲身阅读感受分享,细节画图解释,再也不用担心看不懂论文啦…

C++杂项

作业&#xff1a; 将之前实现的顺序表、栈、队列都更改成模板类 顺序表 #include <iostream>using namespace std;template<typename T>class SeqList { private:T *ptr;int size; //总长度int len 0; //当前顺序表实际长度public://初始…

误差不到1毫米的WGS84与CGCS2000坐标转换工具

我们在《WGS84与CGCS2000坐标的精密转换方法》一文中为你分享了一个WGS84与CGCS2000坐标的精密转换纯理论性的方法。 现在&#xff0c;再为你分享一个据说是误差不到1毫米的WGS84与CGCS2000坐标的转换工具&#xff0c;请从文末查看该工具的领取方法。 WGS84与CGCS2000坐标转换…

人工智能有助于解决 IT/OT 集成安全挑战

思科的一项研究表明&#xff0c;信息技术 (IT) 和运营技术 (OT) 融合所带来的安全问题可以通过人工智能 (AI) 解决&#xff0c;尽管该技术也可能被恶意行为者利用。 该报告由思科和 Sapio Research 联合发布&#xff0c;对 17 个国家的 1,000 名行业专业人士进行了调查&#x…

AWS Network Firewall -NAT网关配置只应许白名单域名出入站

1. 创建防火墙 选择防火墙的归属子网(选择公有子网) 2. 创建规则白名单域名放行 3. 绑定相关规则

HCIP--以太网交换安全(一)

以太网交换安全概述&#xff1a;以太网交换安全是一系列技术和策略的集合&#xff0c;旨在保护以太网交换机免受各种网络攻击和威胁。 端口隔离 一、端口隔离概述&#xff1a; 作用&#xff1a;可以实现同一个VLAN内端口的隔离 优势&#xff1a; 端口隔离功能为用户提供了更…

UE5: Content browser工具编写02

DebugHeader.h 中的全局变量&#xff0c;已经在一个cpp file中被include了&#xff0c;如果在另一个cpp file中再include它&#xff0c;就会有一些conflicts。先全部给加一个static Add static keyword to debug functionsWrap all the functions inside of a namespaceprint …

锐尔15注册机 锐尔文档扫描影像处理系统15功能介绍

锐尔文档扫描影像处理系统是一款全中文操作界面的文件、档案扫描及影像优化处理软件&#xff0c;是目前国内档案数字化行业里专业且优秀的影像优化处理软件。 无论是从纸质文件制作高质量的影像文件&#xff0c;或是检查已经制作好的影像文件&#xff0c;锐尔文档扫描影像处理…

大数据新视界 --大数据大厂之 Druid 实时数据分析平台在大数据中的应用

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

在Windows系统上安装的 Arrow C++ 库

在Windows系统上安装的 Arrow C 库 正文第一步第二步第三步第四步注: 检查是否安装成功 吐槽 正文 第一步 git clone gitgithub.com:apache/arrow.git第二步 打开powershell (好像cmd也可以,不过我试了powershell中不报错,cmd中报错,不是很清楚为什么) 打开arrow的目录 cd …

贝锐洋葱头浏览器随时随地访问教务系统,轻松搞定选课

教育网的“拥堵”早已是老生常谈&#xff0c;学生数量庞大、上网时间集中、带宽有限&#xff0c;导致网络速度慢。尤其是从外部网络访问教育网时&#xff0c;更是因为跨运营商的缘故变得缓慢。 而学校内网也是类似的情况&#xff0c;课余时间和上课时间的网络使用情况差别巨大…

xpath在爬虫中的应用、xpath插件的安装及使用

安装 1、打开谷歌浏览器进入扩展程序安装页面(右上角会有"开发者模式按钮")默认是关闭的&#xff0c;当安装此插件时需要把开发者模式打开。 2、下载下来的xpath_helper是zip格式的&#xff0c;需要解压缩即可安装。 3、重启浏览器&#xff0c;再次点击扩展程序即…