java結(jié)合keytool如何實(shí)現(xiàn)非對(duì)稱加密與解密詳解
前言
參考:java結(jié)合keytool實(shí)現(xiàn)非對(duì)稱簽名與驗(yàn)證
那一篇講簽名,這一篇將加密解密。在java安全體系中,簽名屬于JAAS模塊,加解密屬于JCE模塊。
keytool的使用
keytool是JDK自帶的一個(gè)密鑰庫(kù)管理工具。這里只用到了keytool的部分功能,包括生成密鑰對(duì),導(dǎo)出公鑰等。keytool生成的公鑰/私鑰對(duì)存放到一個(gè)到了一個(gè)文件中,這個(gè)文件有密碼保護(hù),通稱為keystore。
生成密鑰對(duì)
$ keytool -genkey -alias signLegal -keystore examplestanstore2 -validity 1800 -keyalg RSA
生成別名為signLegal的密鑰對(duì),存放在密鑰庫(kù)examplestanstore2中,證書(shū)的有效期是1800天(默認(rèn)是90天)。
輸入一系列的參數(shù)。輸入的參數(shù)遵循了LDAP的風(fēng)格和標(biāo)準(zhǔn)??梢韵胂?,生成的密鑰對(duì)可以看成LDAP的一個(gè)條目。
命令執(zhí)行成功后會(huì)在當(dāng)前目錄下創(chuàng)建一個(gè)叫examplestanstore2的文件。相對(duì)另一篇博文,增加了一個(gè)keyalg參數(shù)。因?yàn)閗eytool默認(rèn)算法是DSA,而DSA只能用于簽名。RSA既能用于簽名,也能用于加密。而本文是研究加密問(wèn)題,只能用RSA算法。
查看密鑰對(duì)
$ keytool -list -keystore examplestanstore2 -v
列出了examplestanstore2密鑰庫(kù)的中所有密鑰對(duì)。-v參數(shù)表示詳細(xì)信息,詳細(xì)信息中有證書(shū)的失效時(shí)間。
導(dǎo)出公鑰證書(shū)
$ keytool -export -keystore examplestanstore2 -alias signLegal -file StanSmith.crt -rfc
導(dǎo)出的公鑰存放在當(dāng)前目錄的StanSmith.crt文件中。講“簽名”的那篇博文沒(méi)有加-rfc參數(shù),導(dǎo)出是個(gè)二進(jìn)制文件(CER格式)。
加上-rfc后,導(dǎo)出的是文本文件(PEM)格式。在下面的測(cè)試中,如果使用CER格式,會(huì)報(bào)錯(cuò) ` No installed provider supports this key: sun.security.provider.DSAPublicKeyImpl`。
java加密和解密
在java程序中,首先從密鑰庫(kù)取出私鑰和公鑰,然后對(duì)測(cè)試字符串進(jìn)行加密。二進(jìn)制的密文轉(zhuǎn)換成字符串輸出到屏幕,然后解密成明文再輸出到屏幕。
GenSig2.java
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.從密鑰庫(kù)中取私鑰 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.根據(jù)命令行參數(shù)取公鑰 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.使用公鑰進(jìn)行加密 String data = "測(cè)試數(shù)據(jù)"; //構(gòu)建加密解密類 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, pubKey);//設(shè)置為加密模式 byte[] jmdata = cipher.doFinal(data.getBytes()); //打印加密后數(shù)據(jù) System.out.println(bytesToHexString(jmdata)); //改為解密模式進(jìn)行解密 cipher.init(Cipher.DECRYPT_MODE, prikey);//會(huì)用私鑰解密 jmdata = cipher.doFinal(jmdata); System.out.println(new String(jmdata)); }catch (Exception e) { e.printStackTrace(); } } //這個(gè)方法用于把二進(jìn)制轉(zhuǎn)換成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(); } }
編譯,并運(yùn)行:
$ javac RSAEntry.java $ java RSAEntry StanSmith.crt 8fceea48e34fdc786bde05459f3366714b650ff04f4e81e52eca139d8ee0b4acbcad019cd496de3589765894b2d5f4a2af38914af614d9e9b73e551ae01830cd6f49505685d7e527e3adc2b7a2a75608068627c0a12b338d3c743a5de2af2de327a0de14b548604e5c8905747aef077852ecfd2eb4a134ca0f3a56b23db8ae4beb07add5ba3725ab3ee0ffa7481494856144ba5004a329cfe2c43078f0cd95aebcbbfc6c1894efafacac90615e549cb8432c125d912a5e54ce4884f633f3e96bd7b61c1d538e38713716367f7ec6f5ca01288e6d96ad9e3d6515147369144390e1d002b1beaf5797966e3b498cc7def754816c99456ef380b3a83366a44415f6 測(cè)試數(shù)據(jù)
本文展示的算法是一種非對(duì)稱算法,計(jì)算較慢。在SSL中,非對(duì)稱算法用于客戶端和服務(wù)器之間交換對(duì)稱加密的一次性密鑰??蛻舳藢⒁粋€(gè)隨機(jī)數(shù)用服務(wù)器的公鑰加密發(fā)給服務(wù)器,如果服務(wù)器持有私鑰,就能解開(kāi)密文獲得隨機(jī)數(shù)(這個(gè)隨機(jī)數(shù)就是對(duì)稱算法的密鑰)。有了對(duì)稱算法密鑰,雙方就可以用對(duì)稱加密進(jìn)行安全通信了。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Springboot實(shí)現(xiàn)高吞吐量異步處理詳解(適用于高并發(fā)場(chǎng)景)
這篇文章主要介紹了Springboot實(shí)現(xiàn)高吞吐量異步處理詳解(適用于高并發(fā)場(chǎng)景),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Mybatis-Plus進(jìn)階分頁(yè)與樂(lè)觀鎖插件及通用枚舉和多數(shù)據(jù)源詳解
這篇文章主要介紹了Mybatis-Plus的分頁(yè)插件與樂(lè)觀鎖插件還有通用枚舉和多數(shù)據(jù)源的相關(guān)介紹,文中代碼附有詳細(xì)的注釋,感興趣的朋友來(lái)看看吧2022-03-03Spring Cloud Zipkin服務(wù)端追蹤服務(wù)
這篇文章主要介紹了Spring Cloud Zipkin服務(wù)端追蹤服務(wù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04Java CountDownLatch計(jì)數(shù)器與CyclicBarrier循環(huán)屏障
CountDownLatch是一種同步輔助,允許一個(gè)或多個(gè)線程等待其他線程中正在執(zhí)行的操作的ASET完成。它允許一組線程同時(shí)等待到達(dá)一個(gè)共同的障礙點(diǎn)2023-04-04java報(bào)錯(cuò):“錯(cuò)誤:編碼GBK?的不可映射字符”解決辦法
當(dāng)Java源代碼中包含中文字符時(shí),我們?cè)谟胘avac編譯時(shí)會(huì)出現(xiàn)“錯(cuò)誤:編碼GBK的不可映射字符”,這篇文章主要給大家介紹了關(guān)于java報(bào)錯(cuò):“錯(cuò)誤:編碼GBK?的不可映射字符”的解決辦法,需要的朋友可以參考下2024-08-08基于Java實(shí)現(xiàn)文件和base64字符串轉(zhuǎn)換
這篇文章主要介紹了基于Java實(shí)現(xiàn)文件和base64字符串轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01Java 8系列之Stream中萬(wàn)能的reduce用法說(shuō)明
這篇文章主要介紹了Java 8系列之Stream中萬(wàn)能的reduce用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08