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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM