公鑰與私鑰


在對稱加密的時代,加密和解密用的是同一個密鑰,這個密鑰既用於加密,又用於解密。這樣做有一個明顯的缺點,如果兩個人之間傳輸文件,兩個人都要知道密鑰,如果是三個人呢,五個人呢?於是就產生了非對稱加密,用一個密鑰進行加密(公鑰),用另一個密鑰進行解密(私鑰)

1.公鑰私鑰原理

張三有兩把鑰匙,一把是公鑰,另一把是私鑰。

 

 

 張三把公鑰送給他的朋友們—-李四、王五、趙六—-每人一把。

 

 李四要給張三寫一封保密的信。她寫完后用張三的公鑰加密,就可以達到保密的效果。

 

 張三收信后,用私鑰解密,就看到了信件內容。這里要強調的是,只要張三的私鑰不泄露,這封信就是安全的,即使落在別人手里,也無法解密。

 

 張三給李四回信,決定采用“數字簽名”。他寫完后先用Hash函數,生成信件的摘要(digest)。然后利用私鑰將摘要進行加密,張三將這個簽名,附在信件下面,一起發給李四。

 

 李四收信后,取下數字簽名,用張三的公鑰解密,得到信件的摘要。由此證明,這封信確實是張三發出的。李四再對信件本身使用Hash函數,將得到的結果,與上一步得到的摘要進行對比。如果兩者一致,就證明這封信未被修改過。

 

 2.生成私鑰公鑰

Spring Security 提供對JWT的支持,我們使用Spring Security 提供的JwtHelper來創建JWT令牌,校驗JWT令牌 等操作。 這里JWT令牌我們采用非對稱算法進行加密,所以我們要先生成公鑰和私鑰。

(1)生成密鑰證書 下邊命令生成密鑰證書,采用RSA 算法每個證書包含公鑰和私鑰

創建一個文件夾,在該文件夾下執行如下命令行:

keytool 
-genkeypair 
-alias changgou 
-keyalg RSA 
-keypass changgou 
-keystore changgou.jks 
-storepass changgou 

Keytool 是一個java提供的證書管理工具

-alias:密鑰的別名
-keyalg:使用的hash算法
-keypass:密鑰的訪問密碼 
-keystore:密鑰庫文件名,xc.keystore保存了生成的證書 
-storepass:密鑰庫的訪問密碼

(2)查詢證書信息

keytool -list -keystore changgou.jks

(3)刪除別名

keytool -delete -alias changgou -keystore changgou.jsk

4.2.3 導出公鑰

openssl是一個加解密工具包,這里使用openssl來導出公鑰信息。

安裝 openssl:http://slproweb.com/products/Win32OpenSSL.html

安裝資料目錄下的Win64OpenSSL-1_1_0g.exe

cmd進入changgou.jks文件所在目錄執行如下命令(如下命令在windows下執行,會把-變成中文方式,請將它改成英文的-):

keytool -list -rfc --keystore changgou.jks | openssl x509 -inform pem -pubkey

 

 將上邊的公鑰拷貝到文本public.key文件中,合並為一行,可以將它放到需要實現授權認證的工程中。

4.2.4 JWT令牌

(1)創建令牌數據

public class Test {
    public static void main(String[] args) {
        /**
         * 密鑰證書文件路徑
         */
        String key_location="changgou.jks";

        /**
         * 密鑰庫的訪問密碼
         */
        String key_password="changgou";

        /**
         * 密鑰的訪問密碼
         */
        String keypwd = "changgou";

        /**
         * 秘鑰別名
         */
        String alias = "changgou";

        /**
         * 訪問證書路徑
         */
        ClassPathResource resource = new ClassPathResource(key_location);
        /**
         * 創建秘鑰工廠
         * 資源路徑
         * 密鑰庫訪問密碼
         */
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resource,key_password.toCharArray());

        /**
         * 讀取秘鑰對(公鑰、私鑰)
         * 密鑰別名
         * 密鑰訪問密碼
         */
        KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias,keypwd.toCharArray());

        /**
         * 獲取私鑰
         */
        RSAPrivateKey rsaPrivate = (RSAPrivateKey) keyPair.getPrivate();

        /**
         * 定義Payload
         */
        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("id", "1");
        tokenMap.put("name", "itheima");
        tokenMap.put("roles", "ROLE_VIP,ROLE_USER");

        /**
         * 生成jwt令牌
         * 用私鑰加密
         */
        Jwt jwt = JwtHelper.encode(JSON.toJSONString(tokenMap), new RsaSigner(rsaPrivate));

        /**
         * 取出令牌
         */
        String encoded = jwt.getEncoded();
        System.out.println(encoded);

    }
}

(2)解析令牌

上面創建令牌后,我們可以對JWT令牌進行解析,這里解析需要用到公鑰,我們可以將之前生成的公鑰public.key拷貝出來用字符串變量token存儲,然后通過公鑰解密。

public class Test2 {
    public static void main(String[] args) {
        /**
         * 令牌
         */
        String token ="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlcyI6IlJPTEVfVklQLFJPTEVfVVNFUiIsIm5hbWUiOiJpdGhlaW1hIiwiaWQiOiIxIn0.oW1h0Xza7vUEgi0rzOlgMLdLicnJ7kFXg6pBjW640sxzeeiPC0cUfXEYAAmmTYEMQtLeivbZeiar-p5ydupUVhTVF8evEzqt64p31DJQ5tsIQ2-moXE8Q6W9JP2MY1sylBdN8rmVmIW6pqBh4KuLkFFalWd851HAzdQg95SvIbyUu6F6M-iZvL4-qcTdakYjpnWKOTWNBighB-hMlaAs6REMXyMsU0wo8DRHyNypUb4vILb_NPjd69ubFhOTUvLkYRtImEk8QNnQ8-l68GhAGmqifxDkNAz3I0f0Mcgfu3OdT056qcR6FG_o1thzOaXRZQliA1B2ZnZ3tepHv6ahxw";

        /**
         * 使用公鑰進行解密
         */
        String publickey ="-----BEGIN PUBLIC KEY-----\n" +
                "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA15w2T+DOwQzFxWa26bFq\n" +
                "1xhYdy49INE7vPC1D6+09P/c1byY6U7N3AStO3eYhT/v5TUwCfXobXZ98e2Gf1/O\n" +
                "KO/TmLFXOcoea9MP0kVcVV/80O6g19tzWDIkBbphO9g5E0lq/VwQYC0Cc3/4jNO0\n" +
                "87d5BwMdlSasqbJjA8MVDXjzupPDl+hw6Wr48motbJGgSzrOpNPZMJK25ylwlqac\n" +
                "TCetcjQXL4tpKcPXOaCEUFwWWxBUtFfwP+nU0PSDTUhwe6UsKtugnkAd1TYn9+bh\n" +
                "78J77CFwpFPxtfutSbP2E8/yxYKufUg6NYo+F3PRQQElTb/aH8zi4n+RIHvec2Zw\n" +
                "HwIDAQAB\n" +
                "-----END PUBLIC KEY-----";

        /**
         * 校驗jwt
         */
        Jwt jwt = JwtHelper.decodeAndVerify(token, new RsaVerifier(publickey));


        /**
         * 獲取Jwt原始內容
         */
        String claims = jwt.getClaims();
        System.out.println(claims);
    }
}

 


免責聲明!

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



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