最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

前端RSA加密java后端解密示例代碼

 更新時間:2024年11月23日 14:49:26   作者:王佑輝  
這篇文章主要介紹了RSA非對稱加密的原理,前端使用公鑰加密數據,后端使用私鑰解密,提供了前端和后端實現的示例代碼,包括依賴、接口、工具類等,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

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;

	@Override
	public 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")
    @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;
/**
 * <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;

	@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;

/**
 * 請求數據的加密信息解密處理<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;

	@Override
	public boolean supports(MethodParameter methodParameter, @NonNull Type targetType, @NonNull Class<? extends HttpMessageConverter<?>> 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<? extends HttpMessageConverter<?>> converterType) {
		return body;
	}

	@NonNull
	@Override
	public 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
	@Override
	public 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());
	}

	@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
@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 加密后的內容
	 */
	@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啟動類

  • 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. 調用截圖

總結 

到此這篇關于前端RSA加密java后端解密的文章就介紹到這了,更多相關前端RSA加密后端解密內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring Cloud超詳細i講解Feign自定義配置與使用

    Spring Cloud超詳細i講解Feign自定義配置與使用

    這篇文章主要介紹了SpringCloud Feign自定義配置與使用,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • 基于springEL表達式詳解及應用

    基于springEL表達式詳解及應用

    這篇文章主要介紹了springEL表達式詳解及應用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java生態(tài)/Redis中使用Lua腳本的過程

    Java生態(tài)/Redis中使用Lua腳本的過程

    這篇文章主要介紹了Java生態(tài)/Redis中如何使用Lua腳本,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • 簡單講解java中throws與throw的區(qū)別

    簡單講解java中throws與throw的區(qū)別

    這篇文章主要介紹了簡單講解java中throws與throw的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • Java多線程實例

    Java多線程實例

    本文給大家介紹java多線程實例,對java多線程知識感興趣的朋友參考下吧
    2015-11-11
  • 淺談Java引用和Threadlocal的那些事

    淺談Java引用和Threadlocal的那些事

    這篇文章主要介紹了Java引用和Threadlocal的那些事,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • Spring Boot 常用注解整理(最全收藏版)

    Spring Boot 常用注解整理(最全收藏版)

    本文系統(tǒng)整理了常用的 Spring/Spring Boot 注解,按照功能分類進行介紹,每個注解都會涵蓋其含義、提供來源、應用場景以及代碼示例,幫助開發(fā)者深入理解和快速檢索,感興趣的朋友跟隨小編一起看看吧
    2025-05-05
  • 使用Thrift實現跨語言RPC的調用

    使用Thrift實現跨語言RPC的調用

    Thrift最大的優(yōu)勢就是可以實現跨語言RPC調用,尤其在一些大廠,微服務各模塊之間使用不同的語言是很常見的,本文就將使用java作為服務端,用python作為客戶端,實現不同語言之間的RPC調用,需要的可以參考下
    2023-10-10
  • 使用postman傳遞list集合后臺springmvc接收

    使用postman傳遞list集合后臺springmvc接收

    這篇文章主要介紹了使用postman傳遞list集合后臺springmvc接收的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java 和 Scala 如何調用變參

    Java 和 Scala 如何調用變參

    這篇文章主要介紹了Java 和 Scala 如何調用變參,幫助大家更好的理解和學習Java與Scala,感興趣的朋友可以了解下
    2020-09-09

最新評論

卢龙县| 西充县| 吴忠市| 威宁| 宁安市| 河津市| 海门市| 霍邱县| 赞皇县| 兴文县| 瑞金市| 合作市| 洛隆县| 临颍县| 清流县| 筠连县| 鄯善县| 乐山市| 濉溪县| 安化县| 涞源县| 双柏县| 龙山县| 罗定市| 海兴县| 攀枝花市| 保德县| 高邑县| 赤壁市| 南陵县| 西林县| 普安县| 宁晋县| 洮南市| 犍为县| 兴海县| 轮台县| 山阴县| 宁波市| 晋中市| 武山县|