數(shù)字證書(shū)應(yīng)用綜合揭秘(包括證書(shū)生成、加密、解密、簽名、驗(yàn)簽)

          引言

          數(shù)字證書(shū)是一個(gè)經(jīng)證書(shū)授權(quán)中心數(shù)字簽名的包含公開(kāi)密鑰擁有者信息以及公開(kāi)密鑰的文件。為現(xiàn)實(shí)網(wǎng)絡(luò)安全化標(biāo)準(zhǔn),如今大部分的 B2B、B2C、P2P、O2O 等商業(yè)網(wǎng)站,含有重要企業(yè)資料個(gè)人資料的信息資信網(wǎng)站,政府機(jī)構(gòu)金融機(jī)構(gòu)等服務(wù)網(wǎng)站大部分都使用了數(shù)字證書(shū)來(lái)加強(qiáng)網(wǎng)絡(luò)的安全性。
          數(shù)字證書(shū)一般由經(jīng)過(guò)國(guó)家認(rèn)證的權(quán)威機(jī)構(gòu)頒發(fā),即CA(例如中國(guó)各地方的CA公司)中心簽發(fā)的證書(shū),也可以由企業(yè)級(jí)CA系統(tǒng)進(jìn)行簽發(fā),例如:Symantec、ResellerClub、數(shù)安時(shí)代等。開(kāi)發(fā)人員也可以通過(guò)工具自動(dòng)生成證書(shū)進(jìn)行開(kāi)發(fā),但不經(jīng)過(guò)認(rèn)證的證書(shū)將被視為無(wú)效證書(shū),不保安全保護(hù),但仍可正常運(yùn)行。
          在這篇文章里將為大家介紹數(shù)字證書(shū)的生成使用過(guò)程,以及對(duì)數(shù)據(jù)進(jìn)行加密、解密、簽名、驗(yàn)簽的使用方式。
          希望能對(duì)各位的學(xué)習(xí)研究有所幫助,當(dāng)中有所錯(cuò)漏的地方敬請(qǐng)點(diǎn)評(píng)。

           

           
          目錄

          一、數(shù)字證書(shū)介紹

          二、加密算法介紹

          三、生成數(shù)字證書(shū)的方式

          四、獲取公鑰與私鑰

          五、數(shù)字證書(shū)加密與解密

          六、數(shù)字證書(shū)簽名與驗(yàn)簽

           
           
           
          一、數(shù)字證書(shū)介紹
           

          1.1 什么是數(shù)字證書(shū)

          數(shù)字證書(shū)就是互聯(lián)網(wǎng)通訊中標(biāo)志通訊各方身份信息的一串?dāng)?shù)字,提供了一種在Internet上驗(yàn)證通信實(shí)體身份的方式,數(shù)字證書(shū)不是數(shù)字身份證,而是身份認(rèn)證機(jī)構(gòu)蓋在數(shù)字身份證上的一個(gè)章或印(或者說(shuō)加在數(shù)字身份證上的一個(gè)簽名)。它是由權(quán)威機(jī)構(gòu)——CA機(jī)構(gòu),又稱(chēng)為證書(shū)授權(quán)(Certificate Authority)中心發(fā)行的,人們可以在網(wǎng)上用它來(lái)識(shí)別對(duì)方的身份。

          最簡(jiǎn)單的證書(shū)包含密鑰、名稱(chēng)以及證書(shū)授權(quán)中心的數(shù)字簽名。數(shù)字證書(shū)還有一個(gè)重要的特征就是只在特定的時(shí)間段內(nèi)有效。數(shù)字證書(shū)是一種權(quán)威性的電子文檔,可以由權(quán)威公正的第三方機(jī)構(gòu),即CA(例如中國(guó)各地方的CA公司)中心簽發(fā)的證書(shū),也可以由企業(yè)級(jí)CA系統(tǒng)進(jìn)行簽發(fā)。
           
           
          圖 V.1.1
          1.2 數(shù)字證書(shū)的分類(lèi)

          從數(shù)字簽名使用對(duì)象的角度分,目前的數(shù)字證書(shū)類(lèi)型主要包括:個(gè)人身份證書(shū)、企業(yè)或機(jī)構(gòu)身份證書(shū)、支付網(wǎng)關(guān)證書(shū)、服務(wù)器證書(shū)、安全電子郵件證書(shū)、個(gè)人代碼簽名證書(shū),這些數(shù)字證書(shū)特點(diǎn)各有不同。

          • 個(gè)人身份證書(shū)

          符合 X.509 標(biāo)準(zhǔn)的數(shù)字安全證書(shū),證書(shū)中包含個(gè)人身份信息和個(gè)人的公鑰,用于標(biāo)識(shí)證書(shū)持有人的個(gè)人身份。數(shù)字安全證書(shū)和對(duì)應(yīng)的私鑰存儲(chǔ)于 E-key  中,用于個(gè)人在網(wǎng)上進(jìn)行合同簽定、定單、錄入審核、操作權(quán)限、支付信息等活動(dòng)中標(biāo)明身份。 

          • 企業(yè)或機(jī)構(gòu)身份證書(shū)

          符合 X.509 標(biāo)準(zhǔn)的數(shù)字安全證書(shū),證書(shū)中包含企業(yè)信息和企業(yè)的公鑰,用于標(biāo)識(shí)證書(shū)持有企業(yè)的身份。數(shù)字安全證書(shū)和對(duì)應(yīng)的私鑰存儲(chǔ)于 E-key 或 IC 卡中,可以用于企業(yè)在電子商務(wù)方面的對(duì)外活動(dòng),如合同簽定、網(wǎng)上證券交易、交易支付信息等方面。 

          • 支付網(wǎng)關(guān)證書(shū)

          支付網(wǎng)關(guān)證書(shū)是證書(shū)簽發(fā)中心針對(duì)支付網(wǎng)關(guān)簽發(fā)的數(shù)字證書(shū),是支付網(wǎng)關(guān)實(shí)現(xiàn)數(shù)據(jù)加解密的主要工具,用于數(shù)字簽名和信息加密。支付網(wǎng)關(guān)證書(shū)僅用于支付網(wǎng)關(guān)提供的服務(wù)(Internet 上各種安全協(xié)議與銀行現(xiàn)有網(wǎng)絡(luò)數(shù)據(jù)格式的轉(zhuǎn)換)。支付網(wǎng)關(guān)證書(shū)只能在有效狀態(tài)下使用。支付網(wǎng)關(guān)證書(shū)不可被申請(qǐng)者轉(zhuǎn)讓。 

          • 服務(wù)器證書(shū)

          符合 X.509 標(biāo)準(zhǔn)的數(shù)字安全證書(shū),證書(shū)中包含服務(wù)器信息和服務(wù)器的公鑰,在網(wǎng)絡(luò)通訊中用于標(biāo)識(shí)和驗(yàn)證服務(wù)器的身份。數(shù)字安全證書(shū)和對(duì)應(yīng)的私鑰存儲(chǔ)于 E-key 中。服務(wù)器軟件利用證書(shū)機(jī)制保證與其他服務(wù)器或客戶(hù)端通信時(shí)雙方身份的真實(shí)性、安全性、可信任度等。 

          • 企業(yè)或機(jī)構(gòu)代碼簽名證書(shū)

          代碼簽名證書(shū)是 CA 中心簽發(fā)給軟件提供商的數(shù)字證書(shū),包含軟件提供商的身份信息、公鑰及 CA 的簽名。軟件提供商使用代碼簽名證書(shū)對(duì)軟件進(jìn)行簽名后放到 Internet 上,當(dāng)用戶(hù)在 Internet 上下載該軟件時(shí),將會(huì)得到提示,從而可以確信:軟件的來(lái)源;軟件自簽名后到下載前,沒(méi)有遭到修改或破壞。代碼簽名證書(shū)可以對(duì) 32-bit .exe 、 .cab 、 .ocx 、 .class 等程序和文件 進(jìn)行簽名。 

          • 安全電子郵件證書(shū)

          符合 X.509 標(biāo)準(zhǔn)的數(shù)字安全證書(shū),通過(guò) IE 或 Netscape 申請(qǐng),用 IE 申請(qǐng)的證書(shū)存儲(chǔ)于 WINDOWS 的注冊(cè)表中,用 NETSCAPE  申請(qǐng)的存儲(chǔ)于個(gè)人用戶(hù)目錄下的文件中。用于安全電子郵件或向需要客戶(hù)驗(yàn)證的 WEB 服務(wù)器(https 服務(wù)) 表明身份。

          • 個(gè)人代碼簽名證書(shū)

          個(gè)人代碼簽名證書(shū)是 CA 中心簽發(fā)給軟件提供人的數(shù)字證書(shū),包含軟件提供個(gè)人的身份信息、公鑰及 CA 的簽名。軟件提供人使用代碼簽名證書(shū)對(duì)軟件進(jìn)行簽名后放到 Internet 上,當(dāng)用戶(hù)在 Internet 上下載該軟件時(shí),將會(huì)得到提示,從而可以確信:軟件的來(lái)源;軟件自簽名后到下載前,沒(méi)有遭到修改或破壞。代碼簽名證書(shū)可以對(duì) 32-bit .exe 、 .cab 、 .ocx 、 .class 等程序和文件進(jìn)行簽名。

          從數(shù)字證書(shū)的技術(shù)角度分,CA中心發(fā)放的證書(shū)分為兩類(lèi):SSL證書(shū)和SET證書(shū)。一般地說(shuō),SSL 證書(shū)(安全套接層)是服務(wù)于銀行對(duì)企業(yè)或企業(yè)對(duì)企業(yè)的電子商務(wù)活動(dòng)的;而SET(安全電子交易)證書(shū)則服務(wù)于持卡消費(fèi)、網(wǎng)上購(gòu)物。雖然它們都是用于識(shí)別身份和數(shù)字簽名的證書(shū),但它們的信任體系完全不同,而且所符合的標(biāo)準(zhǔn)也不一樣。

           

          1.3 數(shù)字證書(shū)的格式

          證書(shū)主要的文件類(lèi)型和協(xié)議有: PEM、DER、PFX、JKS、KDB、CER、KEY、CSR、CRT、CRL 、OCSP、SCEP等。

          1.3.1 PEM 格式

          Openssl使用 PEM(Privacy Enhanced Mail)格式來(lái)存放各種信息,它是 openssl 默認(rèn)采用的信息存放方式。Openssl 中的 PEM 文件一般包含如下信息:
          內(nèi)容類(lèi)型:表明本文件存放的是什么信息內(nèi)容,它的形式為“——-BEGIN XXXX ——”,與結(jié)尾的“——END XXXX——”對(duì)應(yīng)。
          頭信息:表明數(shù)據(jù)是如果被處理后存放,openssl 中用的最多的是加密信息,比如加密算法以及初始化向量 iv。
          信息體:為 BASE64 編碼的數(shù)據(jù)。可以包括所有私鑰(RSA 和 DSA)、公鑰(RSA 和 DSA)和 (x509) 證書(shū)。它存儲(chǔ)用 Base64 編碼的 DER 格式數(shù)據(jù),用 ascii 報(bào)頭包圍,因此適合系統(tǒng)之間的文本模式傳輸。
          使用PEM格式存儲(chǔ)的證書(shū):

          1 -----BEGIN CERTIFICATE-----
          2 MIIF6TCCBNGgAwIBAgIQSSOR8EYFvAGtG16qv0lZ4DANBgkqhkiG9w0BAQsFADBC
          3 MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS
          4 UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE3MDQyNDAwMDAwMFoXDTE5MDQyNDIzNTk1
          5 OVowITEfMB0GA1UEAwwWc2VjdXJpdHkucHVqaW53YW5nLmNvbTCCASIwDQYJKoZI
          6 hvcNAQEBBQADggEPADCCAQoCggEBANrPWriCfyigreL9cVAyEPesYScRd176xhH0
          7 .
          8 -----END CERTIFICATE-----

          使用PEM格式存儲(chǔ)的私鑰:

          1 -----BEGIN RSA PRIVATE KEY-----
          2 MIIF6TCCBNGgAwIBAgIQSSOR8EYFvAGtG16qv0lZ4DANBgkqhkiG9w0BAQsFADBC
          3 MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS
          4 UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE3MDQyNDAwMDAwMFoXDTE5MDQyNDIzNTk1
          5 OVowITEfMB0GA1UEAwwWc2VjdXJpdHkucHVqaW53YW5nLmNvbTCCASIwDQYJKoZI
          6 hvcNAQEBBQADggEPADCCAQoCggEBANrPWriCfyigreL9cVAyEPesYScRd176xhH0
          7 
          8 -----END RSA PRIVATE KEY-----

          使用PEM格式存儲(chǔ)的證書(shū)請(qǐng)求文件:

          1 -----BEGIN CERTIFICATE REQUEST-----
          2 MIIF6TCCBNGgAwIBAgIQSSOR8EYFvAGtG16qv0lZ4DANBgkqhkiG9w0BAQsFADBC
          3 MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS
          4 UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE3MDQyNDAwMDAwMFoXDTE5MDQyNDIzNTk1
          5 OVowITEfMB0GA1UEAwwWc2VjdXJpdHkucHVqaW53YW5nLmNvbTCCASIwDQYJKoZI
          6 hvcNAQEBBQADggEPADCCAQoCggEBANrPWriCfyigreL9cVAyEPesYScRd176xhH0
          7 .
          8 -----END CERTIFICATE REQUEST-----

          1.3.2 DER 格式

          辨別編碼規(guī)則 (DER) 可包含所有私鑰、公鑰和證書(shū)。它是大多數(shù)瀏覽器的缺省格式,并按 ASN1 DER 格式存儲(chǔ)。它是無(wú)報(bào)頭的 - PEM 是用文本報(bào)頭包圍的 DER。
          PFX 或 P12 – 公鑰加密標(biāo)準(zhǔn) #12 (PKCS#12) 可包含所有私鑰、公鑰和證書(shū)。其以二進(jìn)制格式存儲(chǔ),也稱(chēng)為 PFX 文件。通常可以將Apache/OpenSSL使用的“KEY文件 + CRT文件”格式合并轉(zhuǎn)換為標(biāo)準(zhǔn)的PFX文件,你可以將PFX文件格式導(dǎo)入到微軟IIS 5/6、微軟ISA、微軟Exchange Server等軟件。轉(zhuǎn)換時(shí)需要輸入PFX文件的加密密碼。

          1.3.3 JKS格式

          通常可以將Apache/OpenSSL使用的“KEY文件 + CRT文件”格式”轉(zhuǎn)換為標(biāo)準(zhǔn)的Java Key Store(JKS)文件。JKS文件格式被廣泛的應(yīng)用在基于Java的WEB服務(wù)器、應(yīng)用服務(wù)器、中間件。你可以將JKS文件導(dǎo)入到TOMCAT、 WEBLOGIC 等軟件。

          1.3.4 KDB格式

          通常可以將Apache/OpenSSL使用的“KEY文件 + CRT文件”格式轉(zhuǎn)換為標(biāo)準(zhǔn)的IBM KDB文件。KDB文件格式被廣泛的應(yīng)用在IBM的WEB服務(wù)器、應(yīng)用服務(wù)器、中間件。你可以將KDB文件導(dǎo)入到IBM HTTP Server、IBM Websphere 等軟件。

          1.3.5 CSR 格式(證書(shū)請(qǐng)求文件 Certificate Signing Request)

          生成 X509 數(shù)字證書(shū)前,一般先由用戶(hù)提交證書(shū)申請(qǐng)文件,然后由 CA 來(lái)簽發(fā)證書(shū)。大致過(guò)程如下(X509 證書(shū)申請(qǐng)的格式標(biāo)準(zhǔn)為 pkcs#10 和 rfc2314):
          用戶(hù)生成自己的公私鑰對(duì);
          構(gòu)造自己的證書(shū)申請(qǐng)文件,符合 PKCS#10 標(biāo)準(zhǔn)。該文件主要包括了用戶(hù)信息、公鑰以及一些可選的屬性信息,并用自己的私鑰給該內(nèi)容簽名;
          用戶(hù)將證書(shū)申請(qǐng)文件提交給 CA;
          CA 驗(yàn)證簽名,提取用戶(hù)信息,并加上其他信息(比如頒發(fā)者等信息),用 CA 的私鑰簽發(fā)數(shù)字證書(shū);
          說(shuō)明:數(shù)字證書(shū)(如x.509)是將用戶(hù)(或其他實(shí)體)身份與公鑰綁定的信息載體。一個(gè)合法的數(shù)字證書(shū)不僅要符合 X509 格式規(guī)范,還必須有 CA的簽名。用戶(hù)不僅有自己的數(shù)字證書(shū),還必須有對(duì)應(yīng)的私鑰。X509v3數(shù)字證書(shū)主要包含的內(nèi)容有:證書(shū)版本、證書(shū)序列號(hào)、簽名算法、頒發(fā)者信息、有效時(shí)間、持有者信息、公鑰信息、頒發(fā)者 ID、持有者 ID 和擴(kuò)展項(xiàng)。

          1.3.6 OCSP格式(在線(xiàn)證書(shū)狀態(tài)協(xié)議 Online Certificate StatusProtocol,rfc2560)

          用于實(shí)時(shí)表明證書(shū)狀態(tài)。OCSP 客戶(hù)端通過(guò)查詢(xún) OCSP服務(wù)來(lái)確定一個(gè)證書(shū)的狀態(tài),可以提供給使用者一個(gè)或多個(gè)數(shù)字證書(shū)的有效性資料,它建立一個(gè)可實(shí)時(shí)響應(yīng)的機(jī)制,讓用戶(hù)可以實(shí)時(shí)確認(rèn)每一張證書(shū)的有效性,解決由CRL引發(fā)的安全問(wèn)題。。OCSP 可以通過(guò) HTTP協(xié)議來(lái)實(shí)現(xiàn)。rfc2560 定義了 OCSP 客戶(hù)端和服務(wù)端的消息格式。

          1.3.7 CRL格式(證書(shū)吊銷(xiāo)列表 Certification Revocation List)

          是一種包含撤銷(xiāo)的證書(shū)列表的簽名數(shù)據(jù)結(jié)構(gòu)。CRL是證書(shū)撤銷(xiāo)狀態(tài)的公布形式,CRL 就像信用卡的黑名單,用于公布某些數(shù)字證書(shū)不再有效。CRL是一種離線(xiàn)的證書(shū)狀態(tài)信息。它以一定的周期進(jìn)行更新。CRL 可以分為完全 CRL和增量 CRL。在完全 CRL中包含了所有的被撤銷(xiāo)證書(shū)信息,增量 CRL 由一系列的 CRL 來(lái)表明被撤銷(xiāo)的證書(shū)信息,它每次發(fā)布的 CRL 是對(duì)前面發(fā)布 CRL的增量擴(kuò)充。基本的 CRL 信息有:被撤銷(xiāo)證書(shū)序列號(hào)、撤銷(xiāo)時(shí)間、撤銷(xiāo)原因、簽名者以及 CRL 簽名等信息。基于 CRL的驗(yàn)證是一種不嚴(yán)格的證書(shū)認(rèn)證。CRL 能證明在 CRL 中被撤銷(xiāo)的證書(shū)是無(wú)效的。但是,它不能給出不在 CRL中的證書(shū)的狀態(tài)。如果執(zhí)行嚴(yán)格的認(rèn)證,需要采用在線(xiàn)方式進(jìn)行認(rèn)證,即 OCSP認(rèn)證。一般是由CA簽名的一組電子文檔,包括了被廢除證書(shū)的唯一標(biāo)識(shí)(證書(shū)序列號(hào)),CRL用來(lái)列出已經(jīng)過(guò)期或廢除的數(shù)字證書(shū)。它每隔一段時(shí)間就會(huì)更新,因此必須定期下載該清單,才會(huì)取得最新信息。

          1.3.8 SCEP (簡(jiǎn)單證書(shū)注冊(cè)協(xié)議)

          基于文件的證書(shū)登記方式需要從您的本地計(jì)算機(jī)將文本文件復(fù)制和粘貼到證書(shū)發(fā)布中心,和從證書(shū)發(fā)布中心復(fù)制和粘貼到您的本地計(jì)算機(jī)。 SCEP可以自動(dòng)處理這個(gè)過(guò)程但是CRLs仍然需要手工的在本地計(jì)算機(jī)和CA發(fā)布中心之間進(jìn)行復(fù)制和粘貼。

          1.3.9 PKCS7 (加密消息語(yǔ)法(pkcs7)

          是各種消息存放的格式標(biāo)準(zhǔn)。這些消息包括:數(shù)據(jù)、簽名數(shù)據(jù)、數(shù)字信封、簽名數(shù)字信封、摘要數(shù)據(jù)和加密數(shù)據(jù)。

          1.3.10 PKCS12 (個(gè)人數(shù)字證書(shū)標(biāo)準(zhǔn),Public Key Cryptography Standards #12)

          包含了公鑰和私鑰的二進(jìn)制格式的證書(shū)形式,一般以 pfx 作為證書(shū)文件后綴名。用于存放用戶(hù)證書(shū)、crl、用戶(hù)私鑰以及證書(shū)鏈,pkcs12 中的私鑰是加密存放的。

          1.3.11 CER   一般指使用DER格式的證書(shū)

          CER 證書(shū)一般是以 DER 二進(jìn)制編碼的證書(shū),證書(shū)中沒(méi)有私鑰,以 *.cer 作為證書(shū)文件后綴名。證書(shū)可以以 BASE64 編碼輸出,以Base64 編碼的證書(shū)證書(shū)中沒(méi)有私鑰,BASE64 編碼格式的證書(shū)文件,也是以 *.cer 作為證書(shū)文件后綴名。

          1.3.12 CRT    證書(shū)文件,可以是PEM格式

          1.3.13 KEY   一般指PEM格式的私鑰文件

          回到目錄
           
          二、加密算法介紹

          在生成數(shù)據(jù)證書(shū)是用戶(hù)可選擇不同的加密方式對(duì)數(shù)據(jù)進(jìn)行加密,常見(jiàn)的加密算法可以分成三類(lèi),對(duì)稱(chēng)加密算法,非對(duì)稱(chēng)加密算法和Hash算法。

          2.1 對(duì)稱(chēng)加密

          在對(duì)稱(chēng)加密算法中,加密使用的密鑰和解密使用的密鑰是相同的。也就是說(shuō),加密和解密都是使用的同一個(gè)密鑰。因此對(duì)稱(chēng)加密算法要保證安全性的話(huà),密鑰要做好保密,只能讓使用的人知道,不能對(duì)外公開(kāi)。在對(duì)稱(chēng)加密算法中,加密和解密都是使用同一個(gè)密鑰,不區(qū)分公鑰和私鑰。

          對(duì)稱(chēng)加密算法的優(yōu)點(diǎn)在于加解密的高速度和使用長(zhǎng)密鑰時(shí)的難破解性。假設(shè)兩個(gè)用戶(hù)需要使用對(duì)稱(chēng)加密方法加密然后交換數(shù)據(jù),則用戶(hù)最少需要2個(gè)密鑰并交換使用,如果企業(yè)內(nèi)用戶(hù)有n個(gè),則整個(gè)企業(yè)共需要n×(n-1) 個(gè)密鑰,密鑰的生成和分發(fā)將成為企業(yè)信息部門(mén)的惡夢(mèng)。對(duì)稱(chēng)加密算法的安全性取決于加密密鑰的保存情況,但要求企業(yè)中每一個(gè)持有密鑰的人都保守秘密是不可能的,他們通常會(huì)有意無(wú)意的把密鑰泄漏出去——如果一個(gè)用戶(hù)使用的密鑰被入侵者所獲得,入侵者便可以讀取該用戶(hù)密鑰加密的所有文檔,如果整個(gè)企業(yè)共用一個(gè)加密密鑰,那整個(gè)企業(yè)文檔的保密性便無(wú)從談起。

          常見(jiàn)的對(duì)稱(chēng)加密算法:DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES。
          DES是一種分組數(shù)據(jù)加密技術(shù)(先將數(shù)據(jù)分成固定長(zhǎng)度的小數(shù)據(jù)塊,之后進(jìn)行加密),速度較快,適用于大量數(shù)據(jù)加密,而3DES是一種基于DES的加密算法,使用3個(gè)不同密匙對(duì)同一個(gè)分組數(shù)據(jù)塊進(jìn)行3次加密,如此以使得密文強(qiáng)度更高。
          相較于DES和3DES算法而言,AES算法有著更高的速度和資源使用效率,安全級(jí)別也較之更高了,被稱(chēng)為下一代加密標(biāo)準(zhǔn)。

          2.2 非對(duì)稱(chēng)加密

          在非對(duì)稱(chēng)加密算法中,加密使用的密鑰和解密使用的密鑰是不相同的,也稱(chēng)為公私鑰加密,也就是說(shuō)加密使用的密鑰和解密使用的密鑰不同。

          假設(shè)兩個(gè)用戶(hù)要加密交換數(shù)據(jù),雙方交換公鑰,使用時(shí)一方用對(duì)方的公鑰加密,另一方即可用自己的私鑰解密。如果企業(yè)中有n個(gè)用戶(hù),企業(yè)需要生成n對(duì)密鑰,并分發(fā)n個(gè)公鑰。由于公鑰是可以公開(kāi)的,用戶(hù)只要保管好自己的私鑰即可,因此加密密鑰的分發(fā)將變得十分簡(jiǎn)單。同時(shí),由于每個(gè)用戶(hù)的私鑰是唯一的,其他用戶(hù)除了可以可以通過(guò)信息發(fā)送者的公鑰來(lái)驗(yàn)證信息的來(lái)源是否真實(shí),還可以確保發(fā)送者無(wú)法否認(rèn)曾發(fā)送過(guò)該信息。非對(duì)稱(chēng)加密的缺點(diǎn)是加解密速度要遠(yuǎn)遠(yuǎn)慢于對(duì)稱(chēng)加密,在某些極端情況下,甚至能比非對(duì)稱(chēng)加密慢上1000倍。

          常見(jiàn)的非對(duì)稱(chēng)加密算法:RSA、ECC(移動(dòng)設(shè)備用)、Diffie-Hellman、El Gamal、DSA(數(shù)字簽名用)。
          RSA和DSA的安全性及其它各方面性能都差不多,而ECC較之則有著很多的性能優(yōu)越,包括處理速度,帶寬要求,存儲(chǔ)空間等等。

          2.3 Hash算法

          Hash算法特別的地方在于它是一種單向算法,用戶(hù)可以通過(guò)Hash算法對(duì)目標(biāo)信息生成一段特定長(zhǎng)度的唯一的Hash值,卻不能通過(guò)這個(gè)Hash值重新獲得目標(biāo)信息。因此Hash算法常用在不可還原的密碼存儲(chǔ)、信息完整性校驗(yàn)等。

          常見(jiàn)的Hash算法:MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1。
          這幾種算法只生成一串不可逆的密文,經(jīng)常用其效驗(yàn)數(shù)據(jù)傳輸過(guò)程中是否經(jīng)過(guò)修改,因?yàn)橄嗤纳伤惴▽?duì)于同一明文只會(huì)生成唯一的密文,若相同算法生成的密文不同,則證明傳輸數(shù)據(jù)進(jìn)行過(guò)了修改。通常在數(shù)據(jù)傳說(shuō)過(guò)程前,使用MD5和SHA1算法均需要發(fā)送和接收數(shù)據(jù)雙方在數(shù)據(jù)傳送之前就知道密匙生成算法,而HMAC與之不同的是需要生成一個(gè)密匙,發(fā)送方用此密匙對(duì)數(shù)據(jù)進(jìn)行摘要處理(生成密文),接收方再利用此密匙對(duì)接收到的數(shù)據(jù)進(jìn)行摘要處理,再判斷生成的密文是否相同。
          加密算法的效能通常可以按照算法本身的復(fù)雜程度、密鑰長(zhǎng)度(密鑰越長(zhǎng)越安全)、加解密速度等來(lái)衡量。上述的算法中,除了DES密鑰長(zhǎng)度不夠、MD2速度較慢已逐漸被淘汰外,其他算法仍在目前的加密系統(tǒng)產(chǎn)品中使用。

           

          回到目錄
           
          三、生成數(shù)字證書(shū)的方式

          數(shù)字證書(shū)可以通過(guò)在線(xiàn)工具,腳本代碼,KEYTOOL工具,OPEN SSL工具等多種方式生成。下面以常用的RSA非對(duì)稱(chēng)加密為例子,向大家介紹幾種常用的數(shù)字證書(shū)生成方式。

          3.1 利用KEYTOOL工具生成數(shù)字證書(shū)

          KEYTOOL 是個(gè)密鑰和證書(shū)管理工具,可以在 JAVA 環(huán)境下管理安全鑰匙與證書(shū)的生成與安裝。它還是一個(gè)有效的安全鑰匙和證書(shū)的管理工具,使用戶(hù)能夠管理自己的公鑰/私鑰對(duì)及相關(guān)證書(shū)。它管理一個(gè)存儲(chǔ)了私有鑰匙和驗(yàn)證相應(yīng)公共鑰匙的與它們相關(guān)聯(lián)的X.509 證書(shū)鏈的keystore(相當(dāng)一個(gè)數(shù)據(jù)庫(kù),里面可存放多個(gè)X.509標(biāo)準(zhǔn)的證書(shū))。能夠使用戶(hù)使用數(shù)字簽名來(lái)管理他們自己的私有/公共鑰匙對(duì),管理用來(lái)作自我鑒定的相關(guān)的證書(shū),管理數(shù)據(jù)完整性和鑒定服務(wù),還能使用戶(hù)在通信時(shí)緩存它們的公共鑰匙。

          3.1.1 KEYTOOL命令介紹

          KEYTOOL通是以keytool開(kāi)關(guān),當(dāng)中常用命令有: 

          1 keytool -genkey -alias casserver -keypass cas123 -keyalg RSA -keystore casserver.keystore -validity 365
          2 keytool -export -alias casserver -storepass cas123 -file casserver.cer -keystore casserver.keystore
          3 keytool -import -trustcacerts -alias casserver -storepass cas123 -file casserver.cer –keystore cacerts
          • -genkey      在用戶(hù)主目錄中創(chuàng)建一個(gè)默認(rèn)文件".keystore",還會(huì)產(chǎn)生一個(gè)mykey的別名,mykey中包含用戶(hù)的公鑰、私鑰和證書(shū)
            在沒(méi)有指定生成位置的情況下,keystore會(huì)存在用戶(hù)系統(tǒng)默認(rèn)目錄,如:對(duì)于window xp系統(tǒng),會(huì)生成在系統(tǒng)的C:/Documents and Settings/UserName/文件名為“.keystore”
          • -alias       產(chǎn)生別名  -keystore 指定密鑰庫(kù)的名稱(chēng)(產(chǎn)生的各類(lèi)信息將不在.keystore文件中)  -keyalg  指定密鑰的算法 (如 RSA  DSA(如果不指定默認(rèn)采用DSA))
          • -validity    指定創(chuàng)建的證書(shū)有效期多少天-keysize     指定密鑰長(zhǎng)度
          • -storepass   指定密鑰庫(kù)的密碼(獲取keystore信息所需的密碼)
          • -keypass     指定別名條目的密碼(私鑰的密碼)
          • -dname       指定證書(shū)擁有者信息 
            例如:  "CN=名字與姓氏,OU=組織單位名稱(chēng),O=組織名稱(chēng),L=城市或區(qū)域名稱(chēng),ST=州或省份名稱(chēng),C=單位的兩字母國(guó)家代碼"
          • -list        顯示密鑰庫(kù)中的證書(shū)信息      
            例如: keytool -list -v -keystore 是指定 keystore -storepass 密碼 -v 顯示密鑰庫(kù)中的證書(shū)詳細(xì)信息
          • -export      將別名指定的證書(shū)導(dǎo)出到文件  
            例如:keytool -export -alias 需要導(dǎo)出的別名 -keystore 指定keystore -file 指定導(dǎo)出的證書(shū)位置及證書(shū)名稱(chēng) -storepass 密碼
          • -file            參數(shù)指定導(dǎo)出到文件的文件名
          • -delete       刪除密鑰庫(kù)中某條目    
            例如:keytool -delete -alias 指定需刪除的別  -keystore 指定keystore  -storepass 密碼
          • -printcert   查看導(dǎo)出的證書(shū)信息     
            例如:keytool -printcert -file leslie.crt
          • -keypasswd   修改密鑰庫(kù)中指定條目口令    
            例如:keytool -keypasswd -alias 需修改的別名 -keypass 舊密碼 -new  新密碼  -storepass keystore密碼  -keystore sage
          • -storepasswd 修改keystore口令      
            例如:keytool -storepasswd -keystore c:/leslie.keystore(需修改口令的keystore) -storepass 123456(原始密碼) -new 888888(新密碼)
          • -import      將已簽名數(shù)字證書(shū)導(dǎo)入密鑰庫(kù) 
            例如: keytool -import -alias 指定導(dǎo)入條目的別名 -keystore 指定keystore -file 需導(dǎo)入的證書(shū)

          3.1.2 生成 *.keystore 文件流程

          首先執(zhí)行以下命令,分別輸入密鑰庫(kù)口令、姓名,單位,組織,城市,省份,國(guó)家等信息,經(jīng)確認(rèn)后生成對(duì)應(yīng)的 leslie.keystore 文件。注意 *.keystore 文件相當(dāng)于一個(gè)資源庫(kù),后面的公鑰、私鑰、證書(shū)等都依賴(lài)于它生成,必須謹(jǐn)慎保管。

          1 keytool -genkey -alias everygold -keypass 123456 -keyalg RSA -keystore leslie.keystore -validity 365

          提示:  -alias指定別名為 everygold; -keyalg 指定 RSA 算法;-keypass 指定私鑰密碼為123456;
                       -keystore 指定密鑰文件名稱(chēng)為 leslie.keystore;-validity指定有效期為365天。

           

          3.1.3 生成數(shù)字證書(shū)

          根據(jù)上述生成的 leslie.keystore 文件,執(zhí)行以下命令就可以生成數(shù)字證書(shū) leslie.cer

          1 keytool -export -alias everygold -storepass 123456 -file leslie.cer -keystore leslie.keystore

          提示:  -alias 指定別名為 everygold; -storepass 指定私鑰為 123456;
                      -file 指定導(dǎo)出證書(shū)的文件名為 leslie.cer;-keystore 指定之前生成的密鑰文件的文件名

          注意: -alias 和- storepass 必須為生成 leslie.keystore 密鑰文件時(shí)所指定的別名和密碼一致,否則證書(shū)導(dǎo)出失敗

          生成證書(shū) 

          若需要獲取 BASE64 或 DER 證書(shū),可以使用導(dǎo)出功能,在圖片上按 “復(fù)制到文件”,選擇文件格式即可。

          以文本格式打開(kāi)導(dǎo)出的 BASE64 證書(shū),可以看到

          1 -----BEGIN CERTIFICATE-----
          2 MIICRjCCAa+gAwIBAgIEIvzKsDANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD
          3 TjELMAkGA1UECBMCR0QxCzAJBgNVBAcTAkdaMQ4wDAYDVQQKEwVwdWppbjEMMAoG
          4 A1UECxMDU3VuMQ8wDQYDVQQDEwZMZXNsaWUwHhcNMTcwODI5MDMwMjE4WhcNMTgw
          5 ODI5MDMwMjE4WjBWMQswCQYDVQQGEwJDTjELMAkGA1UECBMCR0QxCzAJBgNVBAcT
          6 AkdaMQ4wDAYDVQQKEwVwdWppbjEMMAoGA1UECxMDU3VuMQ8wDQYDVQQDEwZMZXNs
          7 aWUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKFVrCaKFi2GtJjyuWSPrJah
          8 
          9 -----END CERTIFICATE-----

          或者使用以下語(yǔ)句,也可查看到導(dǎo)出的證書(shū)

          1 keytool -list  -rfc -keystore d:/leslie.keystore -storepass 123456

          顯示結(jié)果與上述方法一致

           

          3.2 腳本代碼生成證書(shū)

          若對(duì)KEYTOOL工具不太熟悉的朋友 ,也可通過(guò)JAVA代碼直接生成數(shù)字證書(shū),原理與KEYTOOL生成的基本一致。

           1 public class CerTest {  
           2     public static void main(String[] args){
           3              CerTest test=new CerTest();
           4              //生成 keystore 文件
           5              test.getKeyStore();
           6              //生成 *.cer 證書(shū)文件
           7              test.export();
           8     }
           9 
          10     public void execCommand(String[] arstringCommand) {  
          11         for (int i = 0; i < arstringCommand.length; i++) {  
          12             System.out.print(arstringCommand[i] + " ");  
          13         }  
          14         try {  
          15             Runtime.getRuntime().exec(arstringCommand);  
          16   
          17         } catch (Exception e) {  
          18             System.out.println(e.getMessage());  
          19         }  
          20     }  
          21 
          22     public void execCommand(String arstringCommand) {  
          23         try {  
          24             Runtime.getRuntime().exec(arstringCommand);  
          25               
          26         } catch (Exception e) {  
          27             System.out.println(e.getMessage());  
          28         }  
          29     }  
          30   
          31     /** 
          32      * 生成 *.keystore 
          33      */  
          34     public void getKeyStore() {  
          35         String[] arstringCommand = new String[] {  
          36   
          37         "cmd ", "/k",  
          38                 "start", // cmd Shell命令  
          39   
          40                 "keytool",  
          41                 "-genkey", // -genkey表示生成密鑰  
          42                 "-validity", // -validity指定證書(shū)有效期(單位:天),這里是365天  
          43                 "365",  
          44                 "-keysize",//     指定密鑰長(zhǎng)度  
          45                 "1024",  
          46                 "-alias", // -alias指定別名,這里是everygold 
          47                 "everygold",  
          48                 "-keyalg", // -keyalg 指定密鑰的算法 (如 RSA DSA(如果不指定默認(rèn)采用DSA))  
          49                 "RSA",  
          50                 "-keystore", // -keystore指定存儲(chǔ)位置,這里是d:/leslie.keystore  
          51                 "d:/leslie.keystore",  
          52                 "-dname",// CN=(名字與姓氏), OU=(組織單位名稱(chēng)), O=(組織名稱(chēng)), L=(城市或區(qū)域名稱(chēng)),  
          53                             // ST=(州或省份名稱(chēng)), C=(單位的兩字母國(guó)家代碼)"  
          54                 "CN=(leslie), OU=(everygold), O=(pujinwang), L=(Guangzhou), ST=(Guangdong), C=(CN)",  
          55                 "-storepass", // 指定密鑰庫(kù)的密碼(獲取keystore信息所需的密碼)  
          56                 "123456",   
          57                 "-keypass",// 指定別名條目的密碼(私鑰的密碼)  
          58                 "123456",   
          59                 "-v"// -v 顯示密鑰庫(kù)中的證書(shū)詳細(xì)信息  
          60         };  
          61         execCommand(arstringCommand);  
          62     }  
          63   
          64     /** 
          65      * 導(dǎo)出證書(shū)文件 
          66      */  
          67     public void export() {  
          68   
          69         String[] arstringCommand = new String[] {  
          70   
          71         "cmd ", "/k",  
          72                 "start", // cmd Shell命令  
          73                 "keytool",  
          74                 "-export", // - export指定為導(dǎo)出操作   
          75                 "-keystore", // -keystore指定keystore文件,這里是d:/leslie.keystore  
          76                 "d:/leslie.keystore",  
          77                 "-alias", // -alias指定別名,這里是ss  
          78                 "everygold",  
          79                 "-file",//-file指向?qū)С雎窂?nbsp; 
          80                 "d:/leslie.cer",  
          81                 "-storepass",// 指定密鑰庫(kù)的密碼  
          82                 "123456"   
          83         };  
          84         execCommand(arstringCommand);  
          85       
          86     }  
          87 }

          運(yùn)行成功后,可獲取與3.1節(jié)相同的 leslie.keystore 文件與 leslie.cer 數(shù)字證書(shū)。
          若需要獲取 BASE64 或 DER 證書(shū),也可使用與 3.1.3 節(jié)所述方式獲取 ,在此不再重復(fù)介紹。

           

          3.3 利用在線(xiàn)工具獲取數(shù)字證書(shū)

          如果覺(jué)得使用KEYTOOL或代碼生成數(shù)字證書(shū)過(guò)于繁瑣,可以直接使用在線(xiàn)生成工具生成免費(fèi)數(shù)字證書(shū)。一般在線(xiàn)生成的證書(shū)有效期為 3 個(gè)月到 1年,到期后需要續(xù)費(fèi)或證書(shū)無(wú)效。以下是幾個(gè)常用的在線(xiàn)證書(shū)生成工具,由于用法比較簡(jiǎn)單,在此不作詳細(xì)介紹。

          1. Amazon Web Services (AWS) 是 Amazon.com 旗下的一個(gè)網(wǎng)絡(luò)云服務(wù)站點(diǎn) 
            address:https://aws.amazon.com/cn/?nc2=h_lg
          2. ChinaSSL是亞狐科技旗下專(zhuān)為客戶(hù)提供數(shù)字證書(shū)、網(wǎng)絡(luò)安全服務(wù)的站點(diǎn)
            address:https://csr.chinassl.net/index.html
          3.  MySSL 則是亞洲誠(chéng)信(TRUSTASIA)旗下專(zhuān)為用戶(hù)提供網(wǎng)絡(luò)安全云服務(wù)平臺(tái)
            address:https://myssl.com/csr_create.html

           

          回到目錄

          四、獲取公鑰和私鑰

          在第二節(jié)已經(jīng)介紹過(guò),在加密算法中有對(duì)稱(chēng)加密,非對(duì)稱(chēng)加密,Hash算法等幾類(lèi)。在對(duì)稱(chēng)加密算法中,加密使用的密鑰和解密使用的密鑰是相同的,使用起來(lái)比較簡(jiǎn)單。而公鑰與私鑰一般用于非對(duì)稱(chēng)的加密方式,是安全性最高,使用最為頻密的加密方式,下面幾節(jié),將為大家介紹一下非對(duì)稱(chēng)加密的使用方式。
          公鑰(Public Key)與私鑰(Private Key)是通過(guò)一種算法得到的一個(gè)密鑰對(duì)(即一個(gè)公鑰和一個(gè)私鑰),公鑰是密鑰對(duì)中公開(kāi)的部分,私鑰則是非公開(kāi)的部分。公鑰通常用于加密會(huì)話(huà)密鑰、驗(yàn)證數(shù)字簽名,加密數(shù)據(jù)可以用相應(yīng)的私鑰進(jìn)行數(shù)據(jù)解密。通過(guò)這種算法得到的密鑰對(duì)能保證在世界范圍內(nèi)是唯一的。使用這個(gè)密鑰對(duì)的時(shí)候,如果用其中一個(gè)密鑰加密一段數(shù)據(jù),必須用另一個(gè)密鑰解密。比如用公鑰加密數(shù)據(jù)就必須用私鑰解密,如果用私鑰簽名則必須用公鑰驗(yàn)簽,否則數(shù)據(jù)將不會(huì)成功生成。

          由于使用 KEYTOOL 等工具無(wú)法直接導(dǎo)出公鑰和私鑰,所以必須通過(guò)代碼進(jìn)行導(dǎo)出。而公鑰和私鑰都是二進(jìn)制數(shù)據(jù),所以一般 用Base 64 方式進(jìn)行保存。下面以上述有證書(shū)為例子,導(dǎo)出對(duì)應(yīng)的公鑰與私鑰。

            1 public abstract class Coder {
            2 
            3     /**
            4      * BASE64解密
            5      * 
            6      * @param key
            7      * @return
            8      * @throws Exception
            9      */
           10     public static byte[] decryptBASE64(String key) throws Exception {
           11         return (new BASE64Decoder()).decodeBuffer(key);
           12     }
           13 
           14     /**
           15      * BASE64加密
           16      * 
           17      * @param key
           18      * @return
           19      * @throws Exception
           20      */
           21     public static String encryptBASE64(byte[] key) throws Exception {
           22         return (new BASE64Encoder()).encodeBuffer(key).replace("\r", "").replace("\n", "");
           23     }
           24 }
           25 
           26 public class KeyStoreTool{
           27 
           28     /**
           29      * Java密鑰庫(kù)(Java Key Store,JKS)KEY_STORE
           30      */
           31     public static final String KEY_STORE = "JKS";
           32 
           33     public static final String X509 = "X.509";
           34 
           35     /**
           36      * 獲得KeyStore
           37      * 
           38      * @version   2016-3-16
           39      * @param keyStorePath
           40      * @param password
           41      * @return
           42      * @throws Exception
           43      */
           44     public static KeyStore getKeyStore(String keyStorePath, String password)
           45             throws Exception {
           46         
           47         FileInputStream is = new FileInputStream(keyStorePath);
           48         KeyStore ks = KeyStore.getInstance(KEY_STORE);
           49         ks.load(is, password.toCharArray());
           50         is.close();
           51         return ks;
           52     }
           53 
           54     /**
           55      * 由KeyStore獲得私鑰
           56      * @param keyStorePath
           57      * @param alias
           58      * @param storePass
           59      * @return
           60      * @throws Exception
           61      */
           62     public static PrivateKey getPrivateKey(String keyStorePath, String alias, String storePass, String keyPass) throws Exception {
           63         KeyStore ks = getKeyStore(keyStorePath, storePass);
           64         PrivateKey key = (PrivateKey) ks.getKey(alias, keyPass.toCharArray());
           65         return key;
           66     }
           67     
           68     /**
           69      * 由Certificate獲得公鑰
           70      * @param keyStorePath
           71      *        KeyStore路徑
           72      * @param alias
           73      *        別名
           74      * @param storePass
           75      *        KeyStore訪(fǎng)問(wèn)密碼
           76      * @return
           77      * @throws Exception
           78      */
           79     public static PublicKey getPublicKey(String keyStorePath, String alias, String storePass) throws Exception {
           80         KeyStore ks = getKeyStore(keyStorePath, storePass);
           81         PublicKey key = ks.getCertificate(alias).getPublicKey();
           82         return key;
           83     }
           84        
           85        /**
           86         * 從KeyStore中獲取公鑰,并經(jīng)BASE64編碼
           87         * @param keyStorePath
           88         * @param alias
           89         * @param storePass
           90         * @return
           91         * @throws Exception
           92         */
           93        public static String getStrPublicKey(String keyStorePath, String alias,String storePass) throws Exception{
           94            PublicKey key = getPublicKey(keyStorePath, alias, storePass);
           95            String strKey = Coder.encryptBASE64(key.getEncoded());           
           96            return strKey;
           97        }
           98        
           99        /*
          100         * 獲取經(jīng)BASE64編碼后的私鑰
          101         * @param keyStorePath
          102         * @param alias
          103         * @param storePass
          104         * @param keyPass
          105         * @return
          106         * @throws Exception
          107         */
          108        public static String getStrPrivateKey(String keyStorePath, String alias,String storePass, String keyPass) throws Exception{
          109 
          110            PrivateKey key = getPrivateKey(keyStorePath, alias, storePass, keyPass);
          111            String strKey = Coder.encryptBASE64(key.getEncoded());
          112            return strKey;
          113        }
          114     
          115         public static void main(String args[]){
          116         // 公鑰
          117         String strPublicKey = "";
          118         // 私鑰
          119         String strPrivateKey = "";
          120         
          121         try {
          122                strPublicKey = KeyStoreCoder.getStrPublicKey("d://leslie.keystore", "everygold", "123456");
          123                System.out.println("公鑰 = 【" + strPublicKey + "】");
          124             
          125                strPrivateKey = KeyStoreCoder.getStrPrivateKey("d://leslie.keystore", "everygold", "123456", "123456");
          126                System.out.println("\n私鑰 = 【" + strPrivateKey + "】");
          127             } catch (Exception e1) {
          128                e1.printStackTrace();
          129             }
          130        } 
          131 }

          輸出結(jié)果:

          為方便保存,一般我們會(huì)以Base64位方式把公鑰與私鑰存儲(chǔ)起來(lái)
          publicKey.key 公鑰文件:

          1 -----BEGIN PUBLIC KEY-----
          2 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbUPe3WGFA0QPGCrPrXCUR7K7M
          3 aZQY1btYZrAFjpT/k00zkj/AfcUeEZk6Tf+9mgvZ3KRVvSFaA9kYiVCJOjGfnW2H
          4 fk6u7iOwSs/kwpC5uUzdoWlc5ZX7iC9SACXJgDg/T5HBRpXpsEkxhzWLUKy1FQDC
          5 KduLuEFdzaO4XsSX7QIDAQAB
          6 -----END PUBLIC KEY-----

          privateKey.key 私鑰文件:

           1 -----BEGIN PRIVATE KEY-----
           2 MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBANtQ97dYYUDRA8YK
           3 s+tcJRHsrsxplBjVu1hmsAWOlP+TTTOSP8B9xR4RmTpN/72aC9ncpFW9IVoD2RiJ
           4 UIk6MZ+dbYd+Tq7uI7BKz+TCkLm5TN2haVzllfuIL1IAJcmAOD9PkcFGlemwSTGH
           5 NYtQrLUVAMIp24u4QV3No7hexJftAgMBAAECgYEAkcm/8Yv5kimfFY3VzhXBuqmY
           6 BOAGB4BEel5AkmEWoNIdVrPYVzAD0ZonPn/NCg+V4yvtveTsf7bhIJNfCum5Q8NL
           7 V0YNn5+C1JMZoI9BrRXQjCH30Oy78QfHH9ATigDZ7cr/ke/0hJqO4hks++XlM6Oy
           8 MIuoHy1WUTy5Hm3qbWECQQDvZFDixgwYwiyC9fzEj8NmWyINZx+Ny2DhnZKtKN6r
           9 o7aplGfBPU9NZ/vLQk7AZPS+24hhu7CYlOUhhhoQjWr1AkEA6ogaMAQfPslyrl1W
          10 R2KkPEOVbSSy4IJ5ZIBeJCDisgEtLb9EZ4JzXIfN6usyiJNtwf5k04zEkWBz1f5r
          11 mtTOGQJBAMSodkI1TA6yxPo4thOLvovBZfH4u1UytD3jwnD52CLMdOxOfAWlJhaC
          12 y7iomiU3Sk/X7OvM0kAmYSzvC055vlkCQQDOR0sRNG7u4Gv3pKyAOOhPAPpqdr7F
          13 7LwsgyNKD4qUGajM9c+KYxhoKCIbHybhLRp6Z+/yiXtSik0XyKCIG+fxAkEAsdlz
          14 YkpcG6T38wC0px+Mhq06AIhEF3sy3wLbM3d4ABlNMj3HqlHMPtvCV1L3dpc/8y89
          15 dAPu9OiHf8nyar9eVQ==
          16 -----END PRIVATE KEY-----

          現(xiàn)在 *.keystore 、*.cer 證書(shū)、Base64 證書(shū)、公鑰文件 public.key 私鑰文件 private.key 都已成功生成,下面的章節(jié)將為大家介紹數(shù)據(jù)加密、數(shù)據(jù)解密、數(shù)字簽名、數(shù)字驗(yàn)簽的使用方式。但在此之前,我想先為大家講解一下它們的概念與應(yīng)用場(chǎng)景。
          記得在第二節(jié)曾經(jīng)向大家介紹過(guò)對(duì)稱(chēng)加密與非對(duì)稱(chēng)加密的區(qū)別,由于對(duì)稱(chēng)加密的加密與解密的密鑰都是一致,加密解密雙方都同時(shí)擁有密鑰,容易造成密鑰的泄露。所以一般企業(yè)在不同的業(yè)務(wù)流程下都會(huì)使用不同的密鑰,以防數(shù)據(jù)被泄露。但在大型的企業(yè)中,若使用對(duì)稱(chēng)加密這種方式,企業(yè)將會(huì)產(chǎn)生大量的密鑰,難于管理而且安全性難以保障,并不可取,所以就產(chǎn)生了非對(duì)稱(chēng)加密方式。
          非對(duì)稱(chēng)加密的情況下,在企業(yè)需要獲取客戶(hù)端數(shù)據(jù)時(shí),可以把公鑰向客戶(hù)端公開(kāi),數(shù)據(jù)進(jìn)行加密后,就算加密數(shù)據(jù)被涉取,在沒(méi)有私鑰的情況,數(shù)據(jù)內(nèi)容都不會(huì)被破解,確保了數(shù)據(jù)的安全性。這時(shí),只要企業(yè)保證私鑰的保密前提下,一個(gè)公鑰可以向多個(gè)客戶(hù)端進(jìn)行公開(kāi)用作數(shù)據(jù)傳輸加密。
          而數(shù)字簽名的應(yīng)用場(chǎng)景有點(diǎn)相反,數(shù)字簽名是企業(yè)為客戶(hù)端確認(rèn)數(shù)據(jù)來(lái)源的準(zhǔn)確性而提供的服務(wù)。一般應(yīng)用于政府機(jī)關(guān)、行政部門(mén)、金融行業(yè)、資訊行業(yè)等企業(yè)的數(shù)據(jù)發(fā)布上。數(shù)據(jù)都是由企業(yè)通過(guò)私鑰進(jìn)行簽名,只要客戶(hù)端擁有對(duì)應(yīng)的公鑰,就可以對(duì)數(shù)據(jù)進(jìn)行驗(yàn)簽。只要驗(yàn)簽成功,就能證明該數(shù)據(jù)是來(lái)源此數(shù)字證書(shū)所屬的企業(yè),以保證數(shù)據(jù)來(lái)源的可靠性。一般在國(guó)家政策的發(fā)布,企業(yè)數(shù)據(jù)的公開(kāi),經(jīng)濟(jì)數(shù)據(jù)的公開(kāi)等場(chǎng)景下應(yīng)該最為廣泛。

           

          回到目錄
          五、數(shù)字證書(shū)加密與解密
           
          經(jīng)過(guò)上面的介紹,大家應(yīng)該了解到數(shù)據(jù)加密、數(shù)據(jù)解密、數(shù)字簽名、數(shù)字驗(yàn)簽的使用場(chǎng)景。
          下面將為大家介紹數(shù)據(jù)加密與解密方式:
            1 public abstract class Coder {
            2 
            3     /**
            4      * BASE64解密
            5      * 
            6      * @param key
            7      * @return
            8      * @throws Exception
            9      */
           10     public static byte[] decryptBASE64(String key) throws Exception {
           11         return (new BASE64Decoder()).decodeBuffer(key);
           12     }
           13 
           14     /**
           15      * BASE64加密
           16      * 
           17      * @param key
           18      * @return
           19      * @throws Exception
           20      */
           21     public static String encryptBASE64(byte[] key) throws Exception {
           22         return (new BASE64Encoder()).encodeBuffer(key).replace("\r", "").replace("\n", "");
           23     }
           24 }
           25 
           26 public class MyCoder extends Coder{
           27 
           28     /**
           29      * 使用公鑰加密數(shù)據(jù)
           30      * @param publicKey
           31      * @param srcData
           32      * @return
           33      * @throws Exception
           34      */
           35     public static String encryptByPublicKey(String publicKey, String srcData) throws Exception{
           36         //解密
           37         byte[] pk = Coder.decryptBASE64(publicKey);
           38         X509EncodedKeySpec spec = new X509EncodedKeySpec(pk);
           39         KeyFactory kf = KeyFactory.getInstance("RSA");
           40         //獲取公鑰
           41         PublicKey pubKey = kf.generatePublic(spec);
           42         
           43         // 對(duì)數(shù)據(jù)加密
           44         Cipher cipher = Cipher.getInstance("RSA");
           45         cipher.init(Cipher.ENCRYPT_MODE, pubKey);
           46         
           47         byte[] doFinal = cipher.doFinal(srcData.getBytes());
           48         return encryptBASE64(doFinal);
           49     }
           50     
           51     
           52     /*
           53      * 使用私鑰解密數(shù)據(jù)
           54      * @param privateKey
           55      * @param data
           56      * @return
           57      * @throws Exception
           58      */
           59     public static String descryptByPrivateKey(String privateKey, String data) throws Exception{
           60         // BASE64轉(zhuǎn)碼解密私鑰
           61         byte[] pk = Coder.decryptBASE64(privateKey);
           62         // BASE64轉(zhuǎn)碼解密密文
           63         byte[] text = decryptBASE64(data);
           64         PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(pk);
           65         KeyFactory kf = KeyFactory.getInstance("RSA");
           66         // 獲取私鑰
           67         PrivateKey prvKey = kf.generatePrivate(spec);
           68         
           69         // 對(duì)數(shù)據(jù)加密
           70         Cipher cipher = Cipher.getInstance("RSA");
           71         cipher.init(Cipher.DECRYPT_MODE, prvKey);
           72         
           73         byte[] doFinal = cipher.doFinal(text);
           74         return new String(doFinal);
           75     }
           76 
           77     public static void main(){
           78         // 公鑰
           79         String strPublicKey = "";
           80         // 私鑰
           81         String strPrivateKey = "";
           82         
           83         try {
           84             strPublicKey = KeyStoreTool.getStrPublicKey("d://leslie.keystore", "everygold", "123456");
           85             strPrivateKey = KeyStoreTool.getStrPrivateKey("d://leslie.keystore", "everygold", "123456", "123456");
           86         } catch (Exception e1) {
           87             e1.printStackTrace();
           88         }
           89         
           90         // 原文
           91         String originalText = "原文 = 雖然我窮,但是再窮也要去旅游!";        
           92         System.out.println(originalText);
           93 
           94         try {
           95             // RSA算法 公鑰加密隨機(jī)數(shù)
           96             String secretText = MyCoder.encryptByPublicKey(strPublicKey, originalText);
           97             System.out.println("\n經(jīng)RSA公鑰加密后 = " + secretText);
           98             System.out.println("\n經(jīng)RSA公鑰加密后長(zhǎng)度 = " + secretText.length());
           99             
          100             String text = MyCoder.descryptByPrivateKey(strPrivateKey, secretText);
          101             System.out.println("\n經(jīng)RSA私鑰解密后 = 【" + text + "】");
          102             System.out.println("\n經(jīng)RSA私鑰解密后長(zhǎng)度 = 【" + text.length() + "】");
          103             
          104         } catch (Exception e) {
          105             e.printStackTrace();
          106         }
          107     }
          108 }

          測(cè)試結(jié)果

          當(dāng)然,如果公鑰和私鑰已經(jīng)保存在 public.key 與 private.key 文件里,就可以直接從文件讀取,無(wú)須再通過(guò) *. keystore 文件獲取。
          回到目錄
           
          六、數(shù)字證書(shū)簽名與驗(yàn)簽

          上面介紹過(guò)簽名與驗(yàn)簽主要用于政策機(jī)關(guān),金融機(jī)構(gòu),權(quán)威信息網(wǎng)站對(duì)外公報(bào)信息時(shí)使用。
          一般使用場(chǎng)景下,簽名與驗(yàn)簽往往會(huì)與加密解密同時(shí)使用,企業(yè)會(huì)生成兩對(duì)密鑰,一對(duì)用于對(duì)企業(yè)正式的注冊(cè)名稱(chēng)進(jìn)行簽名,另一對(duì)用于詳細(xì)數(shù)據(jù)的加密。客戶(hù)驗(yàn)簽后就可證明信息來(lái)源的真確性,然后再對(duì)詳細(xì)信息進(jìn)行解密。
          簽名與驗(yàn)簽代碼如下:

           1 public class MySign {
           2     /*
           3     * @param keyStorePath 密鑰庫(kù)存儲(chǔ)路徑
           4     * @param alias 密鑰庫(kù)別名
           5     * @param password 密鑰庫(kù)密碼
           6     */
           7     private static String keyStorePath,alias,password;
           8     
           9     private static Certificate getCertificate() 
          10             throws Exception {
          11         KeyStore keyStore = KeyStoreTool.getKeyStore(keyStorePath, password);
          12         Certificate certificate = keyStore.getCertificate(alias);
          13         return certificate;
          14     }
          15     
          16     public static void setKeyStorePath(String path){
          17         MySign.keyStorePath=path;
          18     }
          19     
          20     public static void setAlias(String alias){
          21         MySign.alias=alias;
          22     }
          23     
          24     public static void setPassword(String password){
          25         MySign.password=password;
          26     }
          27     
          28     /*
          29      * 生成數(shù)據(jù)簽名
          30      * @param data 源數(shù)據(jù)
          31      */
          32     public static byte[] sign(byte[] data) 
          33             throws Exception {
          34         // 獲得證書(shū)
          35         X509Certificate x509Certificate = (X509Certificate) getCertificate();
          36         // 獲取KeyStore
          37         KeyStore keyStore = KeyStoreTool.getKeyStore(keyStorePath, password);
          38         // 取得私鑰
          39         PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
          40         // 構(gòu)建簽名
          41         Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
          42         signature.initSign(privateKey);
          43         signature.update(data);
          44         return signature.sign();
          45     }
          46     
          47     /*
          48      * 生成數(shù)據(jù)簽名并以BASE64編碼
          49      * @param data 源數(shù)據(jù)
          50      */
          51     public static String signToBase64(String data) 
          52             throws Exception {
          53         byte[] byteData=data.getBytes();
          54         return Base64.encode(sign(byteData));
          55     }
          56     
          57     /*
          58      * 對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行驗(yàn)簽
          59      * @param data 已加密數(shù)據(jù)
          60      * @param sign 數(shù)據(jù)簽名[BASE64]
          61      */
          62     public static boolean verifySign(byte[] data, String sign) 
          63             throws Exception {
          64         // 獲得證書(shū)
          65         X509Certificate x509Certificate = (X509Certificate) getCertificate();
          66         // 獲得公鑰
          67         PublicKey publicKey = x509Certificate.getPublicKey();
          68         // 構(gòu)建簽名
          69         Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
          70         signature.initVerify(publicKey);
          71         signature.update(data);
          72         return signature.verify(Base64.decode(sign));
          73     }
          74     
          75     /*
          76      * 對(duì)String數(shù)據(jù)進(jìn)行驗(yàn)簽
          77      * @param data 字符串
          78      * @param sign 數(shù)據(jù)簽名[BASE64]
          79      */
          80     public static boolean verifySginString(String data, String sign) 
          81             throws Exception {
          82         byte[] byteData = data.getBytes();
          83         return verifySign(byteData, sign);
          84     }
          85 
          86     public static void main(String[] args) throws Exception {
          87         
          88         MySign.setKeyStorePath("d://leslie.keystore");
          89         MySign.setPassword("123456");
          90         MySign.setAlias("everygold");
          91         String sign="驢友的天空俱樂(lè)部";
          92         String base64=MySign.signToBase64(sign);
          93         System.out.println("簽名為:"+sign+"\n\n簽名后數(shù)據(jù):\n"+base64);
          94         boolean isRight=MySign.verifySginString(sign,base64);
          95         System.out.println("\n驗(yàn)簽結(jié)果:"+isRight);
          96     }
          97 }

          輸出結(jié)果

           

           
          本章小結(jié)

          文章簡(jiǎn)單介紹了數(shù)字證書(shū)的生成使用過(guò)程,*.cer 證書(shū)的導(dǎo)出,公鑰 public.key,私鑰private.key 的導(dǎo)出等功能,但對(duì)于數(shù)字證書(shū)的功能,本文介紹的可說(shuō)只是冰山一角。一般在政府型項(xiàng)目、大型的金融項(xiàng)目、B2B/B2C/P2P商業(yè)網(wǎng)站,數(shù)字證書(shū)的使用是比較常見(jiàn)。特別是在手機(jī)APP流行的今天,數(shù)字證書(shū)的使用更是越來(lái)越普及化。希望本文對(duì)各位對(duì)數(shù)據(jù)證書(shū)的理解有所幫助。

          對(duì) .NET  開(kāi)發(fā)有興趣的朋友歡迎加入QQ群:230564952 共同探討 !
          對(duì) JAVA 開(kāi)發(fā)有興趣的朋友歡迎加入QQ群:174850571 共同探討 !

           

          服務(wù)類(lèi)工具的應(yīng)用與管理

          Apache2.2+Tomcat7.0整合配置詳解

          Windows Server 2008 R2 負(fù)載平衡入門(mén)篇

          數(shù)字證書(shū)應(yīng)用綜合揭秘(包括證書(shū)生成、加密、解密、簽名、驗(yàn)簽)

           

          作者:風(fēng)塵浪子

          http://www.cnblogs.com/leslies2/p/7442956.html

          原創(chuàng)作品,轉(zhuǎn)載時(shí)請(qǐng)注明作者及出處

          posted on 2017-08-31 15:11 風(fēng)塵浪子 閱讀(1158) 評(píng)論(0)  編輯  收藏


          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           

          導(dǎo)航

          統(tǒng)計(jì)

          公告

           個(gè)人簡(jiǎn)介

          02年畢業(yè)于中山大學(xué)物理系,專(zhuān)門(mén)從事.NET、JAVA的項(xiàng)目開(kāi)發(fā),研究大型企業(yè)系統(tǒng)架構(gòu)。對(duì)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)DDD、面向服務(wù)架構(gòu)SOA、分布式開(kāi)發(fā)、.NET與JAVA的相互調(diào)用等方面有著深厚的興趣。本博客中的文章皆屬原創(chuàng),轉(zhuǎn)載時(shí)請(qǐng)注明出處。


          Java高級(jí)編程

          技術(shù)交流
          歡迎加入以下小組共同探討
          QQ群:
          JAVA 高級(jí)編程 174850571
          騰訊微博群:
          數(shù)碼化時(shí)代 62916150
          新浪微博群:
          一切皆是“云” 1181103

          常用鏈接

          留言簿

          隨筆分類(lèi)(1)

          隨筆檔案(2)

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 菏泽市| 达州市| 色达县| 北川| 辽宁省| 安丘市| 郴州市| 阿勒泰市| 商丘市| 苍溪县| 绥芬河市| 江西省| 平邑县| 巴彦淖尔市| 邓州市| 泰安市| 招远市| 乌拉特后旗| 德安县| 阿勒泰市| 长顺县| 阜新市| 呼伦贝尔市| 涟源市| 平遥县| 兰考县| 永春县| 搜索| 夹江县| 中宁县| 灵璧县| 应城市| 彰化县| 广昌县| 自治县| 大竹县| 昭平县| 共和县| 井陉县| 文水县| 博野县|