Java結合keytool實現非對稱加密和解密

在Java安全體系中,簽名屬於JAAS模塊,加解密屬於JCE模塊。java

keytool的使用

keytool是JDK自帶的一個密鑰庫管理工具。這裏只用到了keytool的部分功能,包括生成密鑰對,導出公鑰等。keytool生成的公鑰/私鑰對存放到一個到了一個文件中,這個文件有密碼保護,通稱爲keystore。算法

生成密鑰對

1安全

$ keytool -genkey -alias signLegal -keystore examplestanstore2 -validity 1800 -keyalg RSA服務器

生成別名爲signLegal的密鑰對,存放在密鑰庫examplestanstore2中,證書的有效期是1800天(默認是90天)。
輸入一系列的參數。輸入的參數遵循了LDAP的風格和標準。能夠想象,生成的密鑰對能夠當作LDAP的一個條目。
命令執行成功後會在當前目錄下建立一個叫examplestanstore2的文件。相對另外一篇博文,增長了一個keyalg參數。由於keytool默認算法是DSA,而DSA只能用於簽名。RSA既能用於簽名,也能用於加密。而本文是研究加密問題,只能用RSA算法。架構

查看密鑰對

1app

$ keytool -list -keystore examplestanstore2 -v分佈式

列出了examplestanstore2密鑰庫的中全部密鑰對。-v參數表示詳細信息,詳細信息中有證書的失效時間。ide

導出公鑰證書

1工具

$ keytool -export -keystore examplestanstore2 -alias signLegal -file StanSmith.crt -rfc源碼分析

導出的公鑰存放在當前目錄的StanSmith.crt文件中。講「簽名」的那篇博文沒有加-rfc參數,導出是個二進制文件(CER格式)。加上-rfc後,導出的是文本文件(PEM)格式。在下面的測試中,若是使用CER格式,會報錯 ` No installed provider supports this key: sun.security.provider.DSAPublicKeyImpl`。

Java加密和解密

在Java程序中,首先從密鑰庫取出私鑰和公鑰,而後對測試字符串進行加密。二進制的密文轉換成字符串輸出到屏幕,而後解密成明文再輸出到屏幕。

GenSig2.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

import java.io.*;

import java.security.KeyStore;

import java.security.PrivateKey;

import java.security.PublicKey;

import javax.crypto.Cipher;

import sun.security.provider.*;

 

public class RSAEntry {

    public static void main(String[] args) {

        try {

        //1.從密鑰庫中取私鑰

        KeyStore ks = KeyStore.getInstance("JKS");

        FileInputStream ksfis = new FileInputStream("examplestanstore2");

        BufferedInputStream ksbufin = new BufferedInputStream(ksfis);

 

        // open keystore and get private key

        // alias is 'signLeal', kpasswd/spasswd is 'vagrant'

        ks.load(ksbufin, "vagrant".toCharArray());

        PrivateKey prikey = (PrivateKey) ks.getKey("signLegal", "vagrant".toCharArray());

 

        //2.根據命令行參數取公鑰

        FileInputStream certfis = new FileInputStream(args[0]);

        java.security.cert.CertificateFactory cf =

            java.security.cert.CertificateFactory.getInstance("X.509");

        java.security.cert.Certificate cert =  cf.generateCertificate(certfis);

        PublicKey pubKey = cert.getPublicKey();

 

        //3.使用公鑰進行加密

        String data = "測試數據";

        //構建加密解密類

        Cipher cipher = Cipher.getInstance("RSA");

        cipher.init(Cipher.ENCRYPT_MODE, pubKey);//設置爲加密模式

        byte[] jmdata = cipher.doFinal(data.getBytes());

        //打印加密後數據

        System.out.println(bytesToHexString(jmdata));

        //改成解密模式進行解密

        cipher.init(Cipher.DECRYPT_MODE, prikey);//會用私鑰解密

        jmdata = cipher.doFinal(jmdata);

        System.out.println(new String(jmdata));

        }catch (Exception e) {

                e.printStackTrace();

        }

    }

    //這個方法用於把二進制轉換成ASCII字符串。

    public static String bytesToHexString(byte[] bytes) {

        if (bytes == null)

            return "null!";

        int len = bytes.length;

        StringBuilder ret = new StringBuilder(2 * len);

 

        for (int i = 0; i < len; ++i) {

            int b = 0xF & bytes[(i)] >> 4;

            ret.append("0123456789abcdef".charAt(b));

            b = 0xF & bytes[(i)];

            ret.append("0123456789abcdef".charAt(b));

        }

 

        return ret.toString();

    }

}

編譯,並運行

1

2

3

4

$ javac RSAEntry.java

$ java RSAEntry StanSmith.crt

8fceea48e34fdc786bde05459f3366714b650ff04f4e81e52eca139d8ee0b4acbcad019cd496de3589765894b2d5f4a2af38914af614d9e9b73e551ae01830cd6f49505685d7e527e3adc2b7a2a75608068627c0a12b338d3c743a5de2af2de327a0de14b548604e5c8905747aef077852ecfd2eb4a134ca0f3a56b23db8ae4beb07add5ba3725ab3ee0ffa7481494856144ba5004a329cfe2c43078f0cd95aebcbbfc6c1894efafacac90615e549cb8432c125d912a5e54ce4884f633f3e96bd7b61c1d538e38713716367f7ec6f5ca01288e6d96ad9e3d6515147369144390e1d002b1beaf5797966e3b498cc7def754816c99456ef380b3a83366a44415f6

測試數據

本文展現的算法是一種非對稱算法,計算較慢。在SSL中,非對稱算法用於客戶端和服務器之間交換對稱加密的一次性密鑰。客戶端將一個隨機數用服務器的公鑰加密發給服務器,若是服務器持有私鑰,就能解開密文得到隨機數(這個隨機數就是對稱算法的密鑰)。有了對稱算法密鑰,雙方就能夠用對稱加密進行安全通訊了。

歡迎學Java和大數據的朋友們加入java架構交流: 855835163 羣內提供免費的架構資料還有:Java工程化、高性能及分佈式、高性能、深刻淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階乾貨的免費直播講解  能夠進來一塊兒學習交流哦

相關文章
相關標籤/搜索