天天看點

Java 實作RSA非對稱加密算法的簽名與驗簽

1.RAS簡介

RSA加密是非對稱加密,由一對秘鑰進行完成加密解密,分别稱為公鑰和私鑰,公鑰加密,私鑰解密,RSA可以完成加密和簽名;

2.加密與簽名的差別

加密是為了防止資訊被洩露,簽名是為了防止資訊被篡改;

3.RSA加密過程

假如B要發消息給A,首先A在本地生産一對秘鑰,公鑰和私鑰,并将公鑰發送給B,B使用公鑰對消息進行加密,然後傳輸給A,A接收到消息後在本地使用私鑰解密;

缺點:這種加密過程保證了消息不被洩露,但是避免不了消息被篡改,假如B發送給A的消息被黑客劫持,他通過公鑰,自己僞造一條消息,通過公鑰加密,發送給A,這樣A收到的消息就不是B發送給A的了;

4.RSA簽名過程

A發送消息給B的時候,用私鑰對消息進行加簽,将加簽後的消息與消息本體發給B,B使用公鑰進行驗簽,如果驗簽出來的内容和消息本身一緻,證明消息才是A回複的;

這樣也會有一個問題,當黑客擷取到消息後,可以使用公鑰驗簽,來檢視消息,并不能防止消息洩露;

總結:公鑰加密、私鑰解密、私鑰簽名、公鑰驗簽。

5.RSA簽名/驗簽執行個體

@Test
void contextLoads() throws Exception {

    /**
     * 1、生成一對RSA密鑰。
     * */
    // 随機生成一對 RAS 密鑰(包含公鑰和私鑰)
    KeyPair keyPair = generateKeyPair();
    // 擷取 公鑰 和 私鑰
    PublicKey publicKey = keyPair.getPublic();
    PrivateKey privateKey = keyPair.getPrivate();

    /**
     * 2.生成原始資料
     * */
    //原始資料 JSON字元串
    String data =  "{" +
            "\"notifyTime\": \"20210519155300\", " +
            "\"notifyType\": \"TEST\", " +
            "\"version\": \"1.0.0TEST\"" +
            "}";

    /**
     * 3.私鑰簽名:對資料進行簽名,計算簽名結果。
     * */
    // 根據指定算法擷取簽名工具
    Signature sign = Signature.getInstance("Sha1WithRSA");
    // 用私鑰初始化簽名工具
    sign.initSign(privateKey);
    // 添加要簽名的資料
    sign.update(data.getBytes());
    //計算簽名結果(簽名資訊)
    byte[] signInfo = sign.sign();
    // 輸出簽名結果的 Base64 字元串
    System.out.println(new BASE64Encoder().encode(signInfo));

    /**
     * 4.公鑰驗簽:用公鑰校驗資料是否被改變
     * */
    // 根據指定算法擷取簽名工具
    sign = Signature.getInstance("Sha1WithRSA");
    // 用公鑰初始化簽名工具
    sign.initVerify(publicKey);
    // 添加要校驗的資料
    sign.update(data.getBytes());
    // 校驗資料的簽名資訊是否正确,
    // 如果傳回 true, 說明該資料的簽名資訊來自該公鑰對應的私鑰,
    // 同一個私鑰的簽名, 資料和簽名資訊一一對應, 隻要其中有一點修改, 則用公鑰無法校驗通過,
    // 是以可以用私鑰簽名, 然後用公鑰來校驗資料的完整性與簽名者(所有者)
    boolean verify = sign.verify(signInfo);
    System.out.println(verify);

    /**
     * 測試資料被修改後的驗簽是否還有效
     * */
    data =  "{" +
            "\"notifyTime\": \"20210519155300\", " +
            "\"notifyType\": \"TEST11\", " +
            "\"version\": \"1.0.0TESTTTT\"" +
            "}";
    sign = Signature.getInstance("Sha1WithRSA");
    sign.initVerify(publicKey);
    sign.update(data.getBytes());
    verify = sign.verify(signInfo);
    System.out.println(verify);
}


/**
 * 随機生成 RSA 密鑰對(包含公鑰和私鑰)
 */
private static KeyPair generateKeyPair() throws Exception {
    // 擷取指定算法的密鑰對生成器
    KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
    // 初始化密鑰對生成器(指定密鑰長度, 使用預設的安全随機數源)
    gen.initialize(2048);
    // 随機生成一對密鑰(包含公鑰和私鑰)
    return gen.generateKeyPair();
}
           

過程中如果有小夥伴遇到問題或者有好的見解可以及時聯系