页面登录数据的加密(前端+后端)
本加密过程使用的 AES+RSA
概要
1.使用AES对传输数据进行加密
AES为对称加密,加密和解决所需要的key是一样的,所以拦截到AES key就可以直接解密,所以需要结果RSA进行加密
2.对AES的key进行RSA加密
RSA为非对称加密,客户端只能获取到publicKey(公钥),而解密只能使用服务器的privateKey(私钥)进行解密,从而保证传输过程的安全性
代码解析
前端代码
<!DOCTYPE html>
<html>
<head><meta name="viewport" content="width=device-width"/><title>Login</title><script src="./jquery-3.7.1.min.js"></script><script src="./jsencrypt.min.js"></script><script src="./crypto-js.min.js"></script><script type="text/javascript">$(function () {// 设置公钥(通常从服务器获取)const publicKey ="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA25Da8op9FPY/wfVk2gnB\nzzT6RPF95+l1tjLG9Z9+jMvFh3JA4C888fuCGN57E3qwdZcNGNZhQoEbve/tCPTw\nn9mbIu62O9/uY6nsACymSHeLahJYlNOVf4YBTsxQ7t2KQr8J8A7i88+cE+9SFdf7\n3Qg+8Wj3BJk0haPA9PUQFm+D/124gfr/j4oTJ5G+OMKwXPhv6Y5j0IOTys1oEItB\nAr79BbK/B0q3cFT6tYQxoRCM8XVLoERmI/V4lX8Vyof9cfPkK+8UGcMKMD59jvXT\nEVNmwtkoWzb8Pcu7GW1pcrSfw9+9hMDgy5j771V0KxmEqklJB7ct6mUgd+x0UsUa\nHwIDAQAB";// 用RSA加密AES密钥const encryptor = new JSEncrypt();encryptor.setPublicKey(publicKey);const key = "abcdef0123456789"; // 16位密钥,测试成功后可改为随机生成16位的字符串const iv = "0123456789abcdef"; // 16位初始向量,测试成功后可改为随机生成16位的字符串const data = "需要加密的数据";const utf8Key = CryptoJS.enc.Utf8.parse(key);const utf8Iv = CryptoJS.enc.Utf8.parse(iv);//AES加密的数据作为传输的参数const encrypted = CryptoJS.AES.encrypt(data, utf8Key, {iv: utf8Iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7});const object = new Object();object.password = encrypted.toString();//RAS加密的key作为参数进行传输object.aesKey = encryptor.encrypt(key);object.iv = iv.toString();console.log(JSON.stringify(object));});</script>
</head>
<body>
<div><input type="text" id="data" value=""/>
</div>
</body>
</html>
后端代码 :
package rsaaes;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;@Slf4j
@RestController
public class LoginController {@AutowiredRsaKeyPair rsaKeyPair;@GetMapping("/getPublicKey")public Map<String, String> getPublicKey() {Map<String, String> ajax = new HashMap<>();ajax.put("publicKey", rsaKeyPair.getPublicKey());return ajax;}@PostMapping("/login")public Map<String, String> login(@RequestBody LoginBody loginBody) {Map<String, String> ajax = new HashMap<>();String password = obtainPassword(loginBody);ajax.put("token", "token自己生成");return ajax;}private String obtainPassword(LoginBody loginBody) {if (StringUtils.isBlank(loginBody.getAesKey())) {return loginBody.getPassword();}return obtainDecryptedPwd(loginBody);}private String obtainDecryptedPwd(LoginBody loginBody) {// 解密AES密钥String aesKey = RSAUtils.decryptPem(rsaKeyPair.getPrivateKey(), loginBody.getAesKey());String decryptedPwd = AESDecryptor.decrypt(loginBody.getPassword(), aesKey, loginBody.getIv());return decryptedPwd;}}
package rsaaes;/*** @Description TODO* @Author chengcheng* @Date 2025/7/2 14:32*/
public class RsaKeyPair {private String publicKey;private String privateKey;public RsaKeyPair(String publicKey, String privateKey) {this.publicKey = publicKey;this.privateKey = privateKey;}public String getPublicKey() {return publicKey;}public void setPublicKey(String publicKey) {this.publicKey = publicKey;}public String getPrivateKey() {return privateKey;}public void setPrivateKey(String privateKey) {this.privateKey = privateKey;}
}
package rsaaes;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;@Configuration
public class SecurityConfig1 {@Beanpublic KeyPairGenerator keyPairGenerator() throws Exception {KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");generator.initialize(2048); // 2048位密钥return generator;}@Beanpublic RsaKeyPair rsaKeyPair(KeyPairGenerator generator) {KeyPair keyPair = generator.generateKeyPair();// 获取公钥和私钥的Base64编码字符串String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());String publicKeyPem = publicKey.replaceAll("(.{64})", "$1\n");String privateKeyPem = privateKey.replaceAll("(.{64})", "$1\n");return new RsaKeyPair(publicKeyPem,privateKeyPem);}public static void main(String[] args) {try {KeyPairGenerator generator = null;generator = KeyPairGenerator.getInstance("RSA");generator.initialize(2048); // 2048位密钥KeyPair keyPair = generator.generateKeyPair();System.out.println("getPrivate---" + keyPair.getPrivate());System.out.println("getPublic---" + keyPair.getPublic());} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}}}
package rsaaes;import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;public class AESDecryptor {public static String decrypt(String encryptedData, String key, String iv) {try {// Base64解码byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);// 创建密钥和初始向量SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");IvParameterSpec ivParameter = new IvParameterSpec(iv.getBytes("UTF-8"));// 初始化CipherCipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameter);// 解密byte[] decryptedBytes = cipher.doFinal(encryptedBytes);return new String(decryptedBytes, "UTF-8");} catch (Exception e) {e.printStackTrace();return null;}}public static void main(String[] args) {String key = "abcdef0123456789";String iv = "0123456789abcdef";String encryptedData = "c3Go0Em03BUc7ytkKRg9rpPc8QLm8wUPrAmfUOJ/ANI=";String decryptedText = decrypt(encryptedData, key, iv);System.out.println("解密结果: " + decryptedText);}
}
package rsaaes;import lombok.Data;/*** @Description TODO* @Author chengcheng* @Date 2025/7/2 15:11*/
@Data
public class LoginBody {public String aesKey;public String iv;private String username;private String password;private String code;private String uuid;
}
package rsaaes;import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.crypto.Cipher;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;/*** RSA算法加密/解密工具类*/
@Slf4j
public class RSAUtils {private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class);/** 算法名称 */private static final String ALGORITHM = "RSA";/** 默认密钥大小 */private static final int KEY_SIZE = 1024;/** 用来指定保存密钥对的文件名和存储的名称 */private static final String PUBLIC_KEY_NAME = "publicKey";private static final String PRIVATE_KEY_NAME = "privateKey";private static final String PUBLIC_FILENAME = "publicKey.properties";private static final String PRIVATE_FILENAME = "privateKey.properties";/** 密钥对生成器 */private static KeyPairGenerator keyPairGenerator = null;private static KeyFactory keyFactory = null;/** 缓存的密钥对 */private static KeyPair keyPair = null;/** Base64 编码/解码器 JDK1.8 */private static Base64.Decoder decoder = Base64.getDecoder();private static Base64.Encoder encoder = Base64.getEncoder();/** 初始化密钥工厂 */static {try {keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);keyFactory = KeyFactory.getInstance(ALGORITHM);} catch (NoSuchAlgorithmException e) {LOGGER.error(e.getMessage(), e);}}/** 私有构造器 */private RSAUtils() {}/*** 生成密钥对* 将密钥分别用Base64编码保存到#publicKey.properties#和#privateKey.properties#文件中* 保存的默认名称分别为publicKey和privateKey*/public static synchronized Map<String, String> generateKeyPair() {try {keyPairGenerator.initialize(KEY_SIZE, new SecureRandom(UUID.randomUUID().toString().replaceAll("-", "").getBytes()));keyPair = keyPairGenerator.generateKeyPair();} catch (InvalidParameterException e) {LOGGER.error("KeyPairGenerator does not support a key length of " + KEY_SIZE + ".", e);} catch (NullPointerException e) {LOGGER.error("RSAUtils#key_pair_gen is null,can not generate KeyPairGenerator instance.", e);}RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();String publicKeyString = encoder.encodeToString(rsaPublicKey.getEncoded());String privateKeyString = encoder.encodeToString(rsaPrivateKey.getEncoded());storeKey(publicKeyString, PUBLIC_KEY_NAME, PUBLIC_FILENAME);storeKey(privateKeyString, PRIVATE_KEY_NAME, PRIVATE_FILENAME);Map<String, String> keyPair = new HashMap<>();keyPair.put("publicKey", publicKeyString);keyPair.put("privateKey", privateKeyString);return keyPair;}/*** 将指定的密钥字符串保存到文件中,如果找不到文件,就创建* @param keyString 密钥的Base64编码字符串(值)* @param keyName 保存在文件中的名称(键)* @param fileName 目标文件名*/private static void storeKey(String keyString, String keyName, String fileName) {Properties properties = new Properties();//存放密钥的绝对地址String path = null;try {path = RSAUtils.class.getClassLoader().getResource(fileName).toString();path = path.substring(path.indexOf(":") + 1);} catch (NullPointerException e) {//如果不存#fileName#就创建LOGGER.warn("storeKey()# " + fileName + " is not exist.Begin to create this file.");String classPath = RSAUtils.class.getClassLoader().getResource("").toString();String prefix = classPath.substring(classPath.indexOf(":") + 1);String suffix = fileName;File file = new File(prefix + suffix);try {file.createNewFile();path = file.getAbsolutePath();} catch (IOException e1) {LOGGER.error(fileName + " create fail.", e1);}}try (OutputStream out = new FileOutputStream(path)) {properties.setProperty(keyName, keyString);properties.store(out, "There is " + keyName);} catch (FileNotFoundException e) {LOGGER.error("ModulusAndExponent.properties is not found.", e);} catch (IOException e) {LOGGER.error("OutputStream output failed.", e);}}/*** 获取密钥字符串* @param keyName 需要获取的密钥名* @param fileName 密钥所在文件* @return Base64编码的密钥字符串*/private static String getKeyString(String keyName, String fileName) {if (RSAUtils.class.getClassLoader().getResource(fileName) == null) {LOGGER.warn("getKeyString()# " + fileName + " is not exist.Will run #generateKeyPair()# firstly.");generateKeyPair();}try (InputStream in = RSAUtils.class.getClassLoader().getResource(fileName).openStream()) {Properties properties = new Properties();properties.load(in);return properties.getProperty(keyName);} catch (IOException e) {LOGGER.error("getKeyString()#" + e.getMessage(), e);}return null;}/*** 从文件获取RSA公钥* @return RSA公钥* @throws InvalidKeySpecException*/public static RSAPublicKey getPublicKey() {try {byte[] keyBytes = decoder.decode(getKeyString(PUBLIC_KEY_NAME, PUBLIC_FILENAME));X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);return (RSAPublicKey) keyFactory.generatePublic(x509EncodedKeySpec);} catch (InvalidKeySpecException e) {LOGGER.error("getPublicKey()#" + e.getMessage(), e);}return null;}/*** 从文件获取RSA私钥* @return RSA私钥* @throws InvalidKeySpecException*/public static RSAPrivateKey getPrivateKey() {try {byte[] keyBytes = decoder.decode(getKeyString(PRIVATE_KEY_NAME, PRIVATE_FILENAME));PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);return (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);} catch (InvalidKeySpecException e) {LOGGER.error("getPrivateKey()#" + e.getMessage(), e);}return null;}/*** RSA公钥加密* @param content 等待加密的数据* @param publicKey RSA 公钥 if null then getPublicKey()* @return 加密后的密文(16进制的字符串)*/public static String encryptByPublic(byte[] content, PublicKey publicKey) {if (publicKey == null) {publicKey = getPublicKey();}try {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);//该密钥能够加密的最大字节长度int splitLength = ((RSAPublicKey) publicKey).getModulus().bitLength() / 8 - 11;byte[][] arrays = splitBytes(content, splitLength);StringBuffer stringBuffer = new StringBuffer();for (byte[] array : arrays) {stringBuffer.append(bytesToHexString(cipher.doFinal(array)));}return stringBuffer.toString();} catch (Exception e) {LOGGER.error("encrypt()#NoSuchAlgorithmException", e);}return null;}/*** RSA私钥加密* @param content 等待加密的数据* @param privateKey RSA 私钥 if null then getPrivateKey()* @return 加密后的密文(16进制的字符串)*/public static String encryptByPrivate(byte[] content, PrivateKey privateKey) {if (privateKey == null) {privateKey = getPrivateKey();}try {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, privateKey);//该密钥能够加密的最大字节长度int splitLength = ((RSAPrivateKey) privateKey).getModulus().bitLength() / 8 - 11;byte[][] arrays = splitBytes(content, splitLength);StringBuffer stringBuffer = new StringBuffer();for (byte[] array : arrays) {stringBuffer.append(bytesToHexString(cipher.doFinal(array)));}return stringBuffer.toString();} catch (Exception e) {LOGGER.error("encrypt()#NoSuchAlgorithmException", e);}return null;}/*** RSA私钥解密* @param content 等待解密的数据* @param privateKey RSA 私钥 if null then getPrivateKey()* @return 解密后的明文*/public static String decryptByPrivate(String content, PrivateKey privateKey) {if (privateKey == null) {privateKey = getPrivateKey();}try {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);//该密钥能够加密的最大字节长度int splitLength = ((RSAPrivateKey) privateKey).getModulus().bitLength() / 8;byte[] contentBytes = hexStringToBytes(content);byte[][] arrays = splitBytes(contentBytes, splitLength);StringBuffer stringBuffer = new StringBuffer();String sTemp = null;for (byte[] array : arrays) {stringBuffer.append(new String(cipher.doFinal(array)));}return stringBuffer.toString();} catch (Exception e) {LOGGER.error("encrypt()#NoSuchAlgorithmException", e);}return null;}/*** RSA公钥解密* @param content 等待解密的数据* @param publicKey RSA 公钥 if null then getPublicKey()* @return 解密后的明文*/public static String decryptByPublic(String content, PublicKey publicKey) {if (publicKey == null) {publicKey = getPublicKey();}try {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, publicKey);//该密钥能够加密的最大字节长度int splitLength = ((RSAPublicKey) publicKey).getModulus().bitLength() / 8;byte[] contentBytes = hexStringToBytes(content);byte[][] arrays = splitBytes(contentBytes, splitLength);StringBuffer stringBuffer = new StringBuffer();String sTemp = null;for (byte[] array : arrays) {stringBuffer.append(new String(cipher.doFinal(array)));}return stringBuffer.toString();} catch (Exception e) {LOGGER.error("encrypt()#NoSuchAlgorithmException", e);}return null;}/*** 根据限定的每组字节长度,将字节数组分组* @param bytes 等待分组的字节组* @param splitLength 每组长度* @return 分组后的字节组*/public static byte[][] splitBytes(byte[] bytes, int splitLength) {//bytes与splitLength的余数int remainder = bytes.length % splitLength;//数据拆分后的组数,余数不为0时加1int quotient = remainder != 0 ? bytes.length / splitLength + 1 : bytes.length / splitLength;byte[][] arrays = new byte[quotient][];byte[] array = null;for (int i = 0; i < quotient; i++) {//如果是最后一组(quotient-1),同时余数不等于0,就将最后一组设置为remainder的长度if (i == quotient - 1 && remainder != 0) {array = new byte[remainder];System.arraycopy(bytes, i * splitLength, array, 0, remainder);} else {array = new byte[splitLength];System.arraycopy(bytes, i * splitLength, array, 0, splitLength);}arrays[i] = array;}return arrays;}/*** 将字节数组转换成16进制字符串* @param bytes 即将转换的数据* @return 16进制字符串*/public static String bytesToHexString(byte[] bytes) {StringBuffer sb = new StringBuffer(bytes.length);String temp = null;for (int i = 0; i < bytes.length; i++) {temp = Integer.toHexString(0xFF & bytes[i]);if (temp.length() < 2) {sb.append(0);}sb.append(temp);}return sb.toString();}/*** 将16进制字符串转换成字节数组* @param hex 16进制字符串* @return byte[]*/public static byte[] hexStringToBytes(String hex) {int len = (hex.length() / 2);hex = hex.toUpperCase();byte[] result = new byte[len];char[] chars = hex.toCharArray();for (int i = 0; i < len; i++) {int pos = i * 2;result[i] = (byte) (toByte(chars[pos]) << 4 | toByte(chars[pos + 1]));}return result;}/*** 将char转换为byte* @param c char* @return byte*/private static byte toByte(char c) {return (byte) "0123456789ABCDEF".indexOf(c);}public static void mainBak(String[] args) {String s = "test";RSAUtils.generateKeyPair();String c1 = RSAUtils.encryptByPublic(s.getBytes(), null);String m1 = RSAUtils.decryptByPrivate(c1, null);String c2 = RSAUtils.encryptByPrivate(s.getBytes(), null);String m2 = RSAUtils.decryptByPublic(c2, null);System.out.println(c1);System.out.println(m1);System.out.println(c2);System.out.println(m2);}public static void main(String[] args) {String s = "test";Map<String, String> map = RSAUtils.generateKeyPair();String c1 = RSAUtils.encryptByPublic(s.getBytes(), null);String m1 = RSAUtils.decryptByPrivate(c1, null);String c2 = RSAUtils.encryptByPrivate(s.getBytes(), null);String m2 = RSAUtils.decryptByPublic(c2, null);System.out.println(c1);System.out.println(m1);System.out.println(c2);System.out.println(m2);String encryptResult = RSAUtils.encryptByPublic(s.getBytes(), obtainRSAPublicKey(map));System.out.println("encryptResult:" + s + "------" + encryptResult);String decryptResult = RSAUtils.decryptByPrivate(encryptResult, obtainRSAPrivateKey(map));System.out.println("decryptResult:" + s + "------" + decryptResult);}private static RSAPrivateKey obtainRSAPrivateKey(Map<String, String> map) {try {byte[] keyBytes = decoder.decode(map.get("privateKey"));PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);return (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);} catch (InvalidKeySpecException e) {LOGGER.error("getPrivateKey()#" + e.getMessage(), e);}return null;}public static RSAPublicKey obtainRSAPublicKey(Map<String, String> map) {try {byte[] keyBytes = decoder.decode(map.get("publicKey"));X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);return (RSAPublicKey) keyFactory.generatePublic(x509EncodedKeySpec);} catch (InvalidKeySpecException e) {LOGGER.error("getPublicKey()#" + e.getMessage(), e);}return null;}public static String decrypt(String privateKey, String encryptResult) {String decryptResult = RSAUtils.decryptByPrivate(encryptResult, obtainRSAPrivateKey(privateKey));return decryptResult;}private static PrivateKey obtainRSAPrivateKey(String privateKey) {try {byte[] keyBytes = decoder.decode(privateKey);PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);return (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);} catch (InvalidKeySpecException e) {LOGGER.error("getPrivateKey()#" + e.getMessage(), e);}return null;}public static String encryptByPublic(String publicKey, String aesKey) {String encryptResult = RSAUtils.encryptByPublic(aesKey.getBytes(), obtainRSAPublicKey(publicKey));return encryptResult;}private static PublicKey obtainRSAPublicKey(String publicKey) {try {byte[] keyBytes = decoder.decode(publicKey);
// byte[] keyBytes =publicKey.getBytes();X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);return (RSAPublicKey) keyFactory.generatePublic(x509EncodedKeySpec);} catch (InvalidKeySpecException e) {LOGGER.error("getPublicKey()#" + e.getMessage(), e);}return null;}public static String decryptPem(String privateKeyPEM, String encryptedData) {try {PrivateKey privateKey = getPrivateKeyFromPEM(privateKeyPEM);String decryptedData = decrypt(encryptedData, privateKey);return decryptedData;} catch (Exception e) {log.error("解密异常",e);return null;}}/*** RSA解密*/public static String decrypt(String encryptedData, PrivateKey privateKey) throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);byte[] decryptedBytes = cipher.doFinal(encryptedBytes);return new String(decryptedBytes, "UTF-8");}/*** 从PEM格式字符串加载私钥*/public static PrivateKey getPrivateKeyFromPEM(String privateKeyPEM) throws Exception {// 清理PEM格式的标记和换行符String privateKeyContent = privateKeyPEM.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s", "");byte[] keyBytes = Base64.getDecoder().decode(privateKeyContent);PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePrivate(spec);}}
<?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>test20250703</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.17.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.4.12</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk15on</artifactId><version>1.59</version></dependency><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.15</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version><scope>provided</scope></dependency></dependencies>
</project>