页面登录数据的加密(前端+后端)

本加密过程使用的 AES+RSA

概要

1.使用AES对传输数据进行加密

AES为对称加密,加密和解决所需要的key是一样的,所以拦截到AES key就可以直接解密,所以需要结果RSA进行加密

2.对AES的key进行RSA加密

RSA为非对称加密,客户端只能获取到publicKey(公钥),而解密只能使用服务器的privateKey(私钥)进行解密,从而保证传输过程的安全性

代码解析

前端代码

javascript 复制代码
<!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>

后端代码 :

java 复制代码
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 {

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

    }


}
java 复制代码
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;
    }
}
java 复制代码
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 {

    @Bean
    public KeyPairGenerator keyPairGenerator() throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(2048); // 2048位密钥
        return generator;
    }

    @Bean
    public 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);
        }

    }

}
java 复制代码
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"));
            
            // 初始化Cipher
            Cipher 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);
    }
}
java 复制代码
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;
}
java 复制代码
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时加1
        int 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>