Java使用SpringBoot生成RSA密钥文件对及校验

Java 使用 SpringBoot 生成 RSA 密钥文件对及校验

1. 新建 SpringBoot 项目

2. 编写代码

2.1 编写 application.yml 文件

SystemConfig:
  rsa-keypair:
    # 加密方式
    algorithm: RSA
    # 初始化大小
    key-size: 1024
    # 公钥文件
    public-key-file: D://publicKey
    # 私钥文件
    private-key-file: D://priavteKey

2.2 编写配置类用于读取 YAML 配置文件属性

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @Author: Arther Lee
 * @Description: 生成密钥对的配置文件
 * @Date: create in 2022-01-29 15:11
 */
@Component
public class GenerateKeyPairConfig {

    @Value("${SystemConfig.rsa-keypair.algorithm}")
    private String algorithm;

    @Value("${SystemConfig.rsa-keypair.key-size}")
    private Integer keySize;

    @Value("${SystemConfig.rsa-keypair.public-key-file}")
    private String publicKeyFile;

    @Value("${SystemConfig.rsa-keypair.private-key-file}")
    private String privateKeyFile;

    /**
     * 获取指定加密算法
     * @return 读取YAML文件的 SystemConfig.rsa-keypair.algorithm 属性
     */
    public String getAlgorithm() {
        return algorithm;
    }

    /**
     * 获取密钥长度,用来初始化
     * @return 读取YAML文件的 SystemConfig.rsa-keypair.key-size 属性
     */
    public Integer getKeySize() {
        return keySize;
    }

    /**
     * 获取公钥存放文件
     * @return 读取YAML文件的 SystemConfig.rsa-keypair.public-key-file 属性
     */
    public String getPublicKeyFile() {
        return publicKeyFile;
    }

    /**
     * 获取私钥存放文件
     * @return 读取YAML文件的 SystemConfig.rsa-keypair.private-key-file 属性
     */
    public String getPrivateKeyFile() {
        return privateKeyFile;
    }
}

2.3 编写 RSA 工具类

import com.example.demo.common.GenerateKeyPairConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: Arther Lee
 * @Description: 密钥对文件工具类
 * @Date: create in 2022-01-28 17:08
 */
@Component
public class GenerateKeyPairUtil {
    @Autowired
    private GenerateKeyPairConfig KeyPairConfig;

    // region 私有方法

    /**
     * 生成密钥对
     * @return 返回map集合,其中包含publicKey与privateKey
     * @throws NoSuchAlgorithmException
     */
    private Map<String, Key> generateKeyPair() throws NoSuchAlgorithmException {
        /**
         * RSA算法要求有一个可信任的随机数源
         */
        SecureRandom secureRandom = new SecureRandom();

        /**
         * 为RSA算法创建一个KeyPairGenerator对象
         */
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyPairConfig.getAlgorithm());

        /**
         * 利用上面的随机数据源初始化这个KeyPairGenerator对象
         */
        keyPairGenerator.initialize(KeyPairConfig.getKeySize(), secureRandom);

        /**
         * 生成密匙对
         */
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        /**
         * 得到公钥
         */
        Key publicKey = keyPair.getPublic();

        /**
         * 得到私钥
         */
        Key privateKey = keyPair.getPrivate();

        Map<String, Key> keyPairMap = new HashMap<>();
        keyPairMap.put("publicKey", publicKey);
        keyPairMap.put("privateKey", privateKey);

        return keyPairMap;
    }

    /**
     * 获取文件中获取密钥对象
     * @param fileName 文件名
     * @return 密钥对象
     */
    private Key getKeyFromFile(String fileName) {
        Key key = null;
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(fileName));
            key = (Key) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return key;
    }

    /**
     * 将密钥对生成到文件中
     */
    private void generateKeyPairToFiles() {
        ObjectOutputStream oosPublicKey = null;
        ObjectOutputStream oosPrivateKey = null;
        try {
            Map<String, Key> keyPairMap = generateKeyPair();
            Key publicKey = keyPairMap.get("publicKey");
            Key privateKey = keyPairMap.get("privateKey");

            oosPublicKey = new ObjectOutputStream(new FileOutputStream(KeyPairConfig.getPublicKeyFile()));
            oosPrivateKey = new ObjectOutputStream(new FileOutputStream(KeyPairConfig.getPrivateKeyFile()));
            oosPublicKey.writeObject(publicKey);
            oosPrivateKey.writeObject(privateKey);

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                /**
                 * 清空缓存,关闭文件输出流
                 */
                oosPublicKey.close();
                oosPrivateKey.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // endregion 私有方法

    // region 公有方法

    /**
     * 初始化密钥对文件
     * @return 返回密钥对信息【publicKey(公钥字符串)、、privateKey(私钥字符串)】
     */
    public Map<String, String> initKeyPair() {
        Map<String, String> keyPairMap = new HashMap<>();
        File publicFile = new File(KeyPairConfig.getPublicKeyFile());
        File privateFile = new File(KeyPairConfig.getPrivateKeyFile());

        /**
         * 判断是否存在公钥和私钥文件
         */
        if (!publicFile.exists() || !privateFile.exists()) {
            generateKeyPairToFiles();
        }

        ObjectInputStream oisPublic = null;
        ObjectInputStream oisPrivate = null;
        Key publicKey = null;
        Key privateKey = null;

        try {
            oisPublic = new ObjectInputStream(new FileInputStream(KeyPairConfig.getPublicKeyFile()));
            oisPrivate = new ObjectInputStream(new FileInputStream(KeyPairConfig.getPrivateKeyFile()));
            publicKey = (Key) oisPublic.readObject();
            privateKey = (Key) oisPrivate.readObject();

            byte[] publicKeyBytes = publicKey.getEncoded();
            byte[] privateKeyBytes = privateKey.getEncoded();

            String publicKeyBase64 = new BASE64Encoder().encode(publicKeyBytes);
            String privateKeyBase64 = new BASE64Encoder().encode(privateKeyBytes);

            /**
             * 公钥字符串
             */
            keyPairMap.put("publicKey", publicKeyBase64);
            /**
             * 私钥字符串
             */
            keyPairMap.put("privateKey", privateKeyBase64);

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                oisPrivate.close();
                oisPublic.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return keyPairMap;
    }

    /**
     * 加密方法
     * @param source 源数据
     * @return 加密后的字符串
     */
    public String encrypt(String source) {
        Key publicKey = getKeyFromFile(KeyPairConfig.getPublicKeyFile());
        BASE64Encoder encoder = new BASE64Encoder();
        String encryptSource = null;
        try {
            /**
             * 得到Cipher对象来实现对源数据的RSA加密
             */
            Cipher cipher = Cipher.getInstance(KeyPairConfig.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] bytes = source.getBytes();

            /**
             * 执行加密操作
             */
            encryptSource = encoder.encode(cipher.doFinal(bytes));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return encryptSource;
    }

    /**
     * 解密方法
     * @param source 密文
     * @return 解密后的字符串
     */
    public String decrypt(String source) {
        Key privateKey = getKeyFromFile(KeyPairConfig.getPrivateKeyFile());
        BASE64Decoder decoder = new BASE64Decoder();
        String decryptSource = null;
        try {
            /**
             * 得到Cipher对象对已用公钥加密的数据进行RSA解密
             */
            Cipher cipher = Cipher.getInstance(KeyPairConfig.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            /**
             * 执行解密操作
             */
            byte[] bytes = decoder.decodeBuffer(source);
            decryptSource = new String(cipher.doFinal(bytes), "UTF-8");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return decryptSource;
    }

    // endregion 公有方法
}

3. 项目测试

3.1 测试代码

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Map;

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    GenerateKeyPairUtil keyPairUtil;

    @Test
    void contextLoads() {
        Map<String, String> keyPairMap = keyPairUtil.initKeyPair();
        String publicKey = keyPairMap.get("publicKey");
        String privateKey = keyPairMap.get("privateKey");
        System.out.println("公钥:");
        System.out.println(publicKey);
        System.out.println();

        System.out.println("私钥:");
        System.out.println(privateKey);
        System.out.println();

        String source = "Hello World";
        System.out.println("待加密字符串:" + source);
        System.out.println();

        String strEncrypt = keyPairUtil.encrypt(source);
        System.out.println("加密后的字符串:");
        System.out.println(strEncrypt);
        System.out.println();

        String strDecrypt = keyPairUtil.decrypt(strEncrypt);
        System.out.println("解密后的字符串:");
        System.out.println(strDecrypt);

    }

}

3.2 测试结果

公钥:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCURAtxRGI7Of19MOb2XoTXFjBG52kr7b11DRJ4
UnyThIuKUjzNSQnW+a1T3fHMfF0w22NiyE2lRpYZ+W6z7MsOhr/EOrXHcFhRd3+bc+j+56aLo8Mp
rYnxBmcc49J5uN8ztg4XSLf4DyEx3CmSh8/mzJxOtoEYDKGL1RapQu2l/QIDAQAB

私钥:
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJREC3FEYjs5/X0w5vZehNcWMEbn
aSvtvXUNEnhSfJOEi4pSPM1JCdb5rVPd8cx8XTDbY2LITaVGlhn5brPsyw6Gv8Q6tcdwWFF3f5tz
6P7npoujwymtifEGZxzj0nm43zO2DhdIt/gPITHcKZKHz+bMnE62gRgMoYvVFqlC7aX9AgMBAAEC
gYEAjl0H36qZ5+S20g6ytr3rL9vOX0a0ZcnRsSLsKTyLAdqzYg209Ci9mf4DwBPMqVyA3vjJZYCP
jbNJTYeEFJ+6GKyIXZeYYXlEzPytrScB+vfro3JUGNnDu4RtFjFPsf3iew872/Vllkq/rNnrXnze
vA7Ea0JxfUEtumdX9CgE8AECQQDo86ocAYcQO+JbX8G9RGcn8SvCieaG9dM7U3fUlrB7XrcJqDo+
ypRqEYZGcdX4iv841bFAqPPFRkhWS+TAMmm9AkEAou9npIFhC0Xe/ncICeWcIn0XHfy/e1cKTE+d
YqfB5RdUcM/qPzrdO2U7p9guscc+e6AbHyhE4MtuoSZu2hxRQQJBAKFzBunEEUSqDFaBxjeTqd7f
4hFBG9lblFtgnQNksMnAOiFiS4PrSPM+VA6MpNxOEVblm6SRs+l8rXPJw6+FAQ0CQEIR0DYt3Hsk
vxLyk4jn2ZNGpCwdxEuwdNWS5yANJJvQBQal2LgBF5qxJyqdh/nA8H5S4wyUWLHK7DZejk7VcsEC
QAn83cKhqcxArrF+jNizom3at44Ag5fdlUahb+ybSNnqeJ6qq5Tagrix6KqVImRAsW1AUQC0r+IN
4FyTzh5WQAw=

待加密字符串:Hello World

加密后的字符串:
IerO2h4VHRN9cD3PoyD8oBlW9yHXu6ZJa9XO1zIi3JhQFIOMye18nx7pR2gI7dr9h41Q5mRiNjz7
3PDu5tLF7nyoIF0IcUHk3Dv4JMfQnfwGEEScatSjai1doIFnpBhUoDJEUY2/qBAUbt14/J1nhKn6
BgeHz0lYrvTVB2TAmus=

解密后的字符串:
Hello World
posted @   爱Ni说不出口  阅读(4089)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示