1. 程式人生 > >數字證書應用綜合揭祕(包括證書生成、加密、解密、簽名、驗籤)

數字證書應用綜合揭祕(包括證書生成、加密、解密、簽名、驗籤)

引言

數字證書是一個經證書授權中心數字簽名的包含公開金鑰擁有者資訊以及公開金鑰的檔案。為現實網路安全化標準,如今大部分的 B2B、B2C、P2P、O2O 等商業網站,含有重要企業資料個人資料的資訊資信網站,政府機構金融機構等服務網站大部分都使用了數字證書來加強網路的安全性。
數字證書一般由經過國家認證的權威機構頒發,即CA(例如中國各地方的CA公司)中心簽發的證書,也可以由企業級CA系統進行簽發,例如:Symantec、ResellerClub、數安時代等。開發人員也可以通過工具自動生成證書進行開發,但不經過認證的證書將被視為無效證書,不保安全保護,但仍可正常執行。
在這篇文章裡將為大家介紹數字證書的生成使用過程,以及對資料進行加密、解密、簽名、驗籤的使用方式。
希望能對各位的學習研究有所幫助,當中有所錯漏的地方敬請點評。

目錄 一、數字證書介紹

1.1 什麼是數字證書

數字證書就是網際網路通訊中標誌通訊各方身份資訊的一串數字,提供了一種在Internet上驗證通訊實體身份的方式,數字證書不是數字身份證,而是身份認證機構蓋在數字身份證上的一個章或印(或者說加在數字身份證上的一個簽名)。它是由權威機構——CA機構,又稱為證書授權(Certificate Authority)中心發行的,人們可以在網上用它來識別對方的身份。

最簡單的證書包含金鑰、名稱以及證書授權中心的數字簽名。數字證書還有一個重要的特徵就是隻在特定的時間段內有效。數字證書是一種權威性的電子文件,可以由權威公正的第三方機構,即CA(例如中國各地方的CA公司)中心簽發的證書,也可以由企業級CA系統進行簽發。
圖 V.1.1 1.2 數字證書的分類

從數字簽名使用物件的角度分,目前的數字證書型別主要包括:個人身份證書、企業或機構身份證書、支付閘道器證書、伺服器證書、安全電子郵件證書、個人程式碼簽名證書,這些數字證書特點各有不同。

  • 個人身份證書

符合 X.509 標準的數字安全證書,證書中包含個人身份資訊和個人的公鑰,用於標識證書持有人的個人身份。數字安全證書和對應的私鑰儲存於 E-key  中,用於個人在網上進行合同簽定、定單、錄入稽核、操作許可權、支付資訊等活動中標明身份。 

  • 企業或機構身份證書

符合 X.509 標準的數字安全證書,證書中包含企業資訊和企業的公鑰,用於標識證書持有企業的身份。數字安全證書和對應的私鑰儲存於 E-key 或 IC 卡中,可以用於企業在電子商務方面的對外活動,如合同簽定、網上證券交易、交易支付資訊等方面。 

  • 支付閘道器證書

支付閘道器證書是證書籤發中心針對支付閘道器簽發的數字證書,是支付閘道器實現資料加解密的主要工具,用於數字簽名和資訊加密。支付閘道器證書僅用於支付閘道器提供的服務(Internet 上各種安全協議與銀行現有網路資料格式的轉換)。支付閘道器證書只能在有效狀態下使用。支付閘道器證書不可被申請者轉讓。 

  • 伺服器證書

符合 X.509 標準的數字安全證書,證書中包含伺服器資訊和伺服器的公鑰,在網路通訊中用於標識和驗證伺服器的身份。數字安全證書和對應的私鑰儲存於 E-key 中。伺服器軟體利用證書機制保證與其他伺服器或客戶端通訊時雙方身份的真實性、安全性、可信任度等。 

  • 企業或機構程式碼簽名證書

程式碼簽名證書是 CA 中心簽發給軟體提供商的數字證書,包含軟體提供商的身份資訊、公鑰及 CA 的簽名。軟體提供商使用程式碼簽名證書對軟體進行簽名後放到 Internet 上,當用戶在 Internet 上下載該軟體時,將會得到提示,從而可以確信:軟體的來源;軟體自簽名後到下載前,沒有遭到修改或破壞。程式碼簽名證書可以對 32-bit .exe 、 .cab 、 .ocx 、 .class 等程式和檔案 進行簽名。 

  • 安全電子郵件證書

符合 X.509 標準的數字安全證書,通過 IE 或 Netscape 申請,用 IE 申請的證書儲存於 WINDOWS 的登錄檔中,用 NETSCAPE  申請的儲存於個人使用者目錄下的檔案中。用於安全電子郵件或向需要客戶驗證的 WEB 伺服器(https 服務) 表明身份。

  • 個人程式碼簽名證書

個人程式碼簽名證書是 CA 中心簽發給軟體提供人的數字證書,包含軟體提供個人的身份資訊、公鑰及 CA 的簽名。軟體提供人使用程式碼簽名證書對軟體進行簽名後放到 Internet 上,當用戶在 Internet 上下載該軟體時,將會得到提示,從而可以確信:軟體的來源;軟體自簽名後到下載前,沒有遭到修改或破壞。程式碼簽名證書可以對 32-bit .exe 、 .cab 、 .ocx 、 .class 等程式和檔案進行簽名。

從數字證書的技術角度分,CA中心發放的證書分為兩類:SSL證書和SET證書。一般地說,SSL 證書(安全套接層)是服務於銀行對企業或企業對企業的電子商務活動的;而SET(安全電子交易)證書則服務於持卡消費、網上購物。雖然它們都是用於識別身份和數字簽名的證書,但它們的信任體系完全不同,而且所符合的標準也不一樣。

1.3 數字證書的格式

證書主要的檔案型別和協議有: PEM、DER、PFX、JKS、KDB、CER、KEY、CSR、CRT、CRL 、OCSP、SCEP等。

1.3.1 PEM 格式

Openssl使用 PEM(Privacy Enhanced Mail)格式來存放各種資訊,它是 openssl 預設採用的資訊存放方式。Openssl 中的 PEM 檔案一般包含如下資訊:
內容型別:表明本檔案存放的是什麼資訊內容,它的形式為“——-BEGIN XXXX ——”,與結尾的“——END XXXX——”對應。
頭資訊:表明資料是如果被處理後存放,openssl 中用的最多的是加密資訊,比如加密演算法以及初始化向量 iv。
資訊體:為 BASE64 編碼的資料。可以包括所有私鑰(RSA 和 DSA)、公鑰(RSA 和 DSA)和 (x509) 證書。它儲存用 Base64 編碼的 DER 格式資料,用 ascii 報頭包圍,因此適合系統之間的文字模式傳輸。
使用PEM格式儲存的證書:

-----BEGIN CERTIFICATE-----
MIIF6TCCBNGgAwIBAgIQSSOR8EYFvAGtG16qv0lZ4DANBgkqhkiG9w0BAQsFADBC
MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS
UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE3MDQyNDAwMDAwMFoXDTE5MDQyNDIzNTk1
OVowITEfMB0GA1UEAwwWc2VjdXJpdHkucHVqaW53YW5nLmNvbTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBANrPWriCfyigreL9cVAyEPesYScRd176xhH0
.............
-----END CERTIFICATE-----


使用PEM格式儲存的私鑰:

-----BEGIN RSA PRIVATE KEY-----
MIIF6TCCBNGgAwIBAgIQSSOR8EYFvAGtG16qv0lZ4DANBgkqhkiG9w0BAQsFADBC
MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS
UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE3MDQyNDAwMDAwMFoXDTE5MDQyNDIzNTk1
OVowITEfMB0GA1UEAwwWc2VjdXJpdHkucHVqaW53YW5nLmNvbTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBANrPWriCfyigreL9cVAyEPesYScRd176xhH0
.............
-----END RSA PRIVATE KEY-----


使用PEM格式儲存的證書請求檔案:

-----BEGIN CERTIFICATE REQUEST-----
MIIF6TCCBNGgAwIBAgIQSSOR8EYFvAGtG16qv0lZ4DANBgkqhkiG9w0BAQsFADBC
MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS
UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE3MDQyNDAwMDAwMFoXDTE5MDQyNDIzNTk1
OVowITEfMB0GA1UEAwwWc2VjdXJpdHkucHVqaW53YW5nLmNvbTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBANrPWriCfyigreL9cVAyEPesYScRd176xhH0
.............
-----END CERTIFICATE REQUEST-----


1.3.2 DER 格式

辨別編碼規則 (DER) 可包含所有私鑰、公鑰和證書。它是大多數瀏覽器的預設格式,並按 ASN1 DER 格式儲存。它是無報頭的 - PEM 是用文字報頭包圍的 DER。
PFX 或 P12 – 公鑰加密標準 #12 (PKCS#12) 可包含所有私鑰、公鑰和證書。其以二進位制格式儲存,也稱為 PFX 檔案。通常可以將Apache/OpenSSL使用的“KEY檔案 + CRT檔案”格式合併轉換為標準的PFX檔案,你可以將PFX檔案格式匯入到微軟IIS 5/6、微軟ISA、微軟Exchange Server等軟體。轉換時需要輸入PFX檔案的加密密碼。

1.3.3 JKS格式

通常可以將Apache/OpenSSL使用的“KEY檔案 + CRT檔案”格式”轉換為標準的Java Key Store(JKS)檔案。JKS檔案格式被廣泛的應用在基於Java的WEB伺服器、應用伺服器、中介軟體。你可以將JKS檔案匯入到TOMCAT、 WEBLOGIC 等軟體。

1.3.4 KDB格式

通常可以將Apache/OpenSSL使用的“KEY檔案 + CRT檔案”格式轉換為標準的IBM KDB檔案。KDB檔案格式被廣泛的應用在IBM的WEB伺服器、應用伺服器、中介軟體。你可以將KDB檔案匯入到IBM HTTP Server、IBM Websphere 等軟體。

1.3.5 CSR 格式(證書請求檔案 Certificate Signing Request)

生成 X509 數字證書前,一般先由使用者提交證書申請檔案,然後由 CA 來簽發證書。大致過程如下(X509 證書申請的格式標準為 pkcs#10 和 rfc2314):
使用者生成自己的公私鑰對;
構造自己的證書申請檔案,符合 PKCS#10 標準。該檔案主要包括了使用者資訊、公鑰以及一些可選的屬性資訊,並用自己的私鑰給該內容簽名;
使用者將證書申請檔案提交給 CA;
CA 驗證簽名,提取使用者資訊,並加上其他資訊(比如頒發者等資訊),用 CA 的私鑰簽發數字證書;
說明:數字證書(如x.509)是將使用者(或其他實體)身份與公鑰繫結的資訊載體。一個合法的數字證書不僅要符合 X509 格式規範,還必須有 CA的簽名。使用者不僅有自己的數字證書,還必須有對應的私鑰。X509v3數字證書主要包含的內容有:證書版本、證書序列號、簽名演算法、頒發者資訊、有效時間、持有者資訊、公鑰資訊、頒發者 ID、持有者 ID 和擴充套件項。

1.3.6 OCSP格式(線上證書狀態協議 Online Certificate StatusProtocol,rfc2560)

用於實時表明證書狀態。OCSP 客戶端通過查詢 OCSP服務來確定一個證書的狀態,可以提供給使用者一個或多個數字證書的有效性資料,它建立一個可實時響應的機制,讓使用者可以實時確認每一張證書的有效性,解決由CRL引發的安全問題。。OCSP 可以通過 HTTP協議來實現。rfc2560 定義了 OCSP 客戶端和服務端的訊息格式。

1.3.7 CRL格式(證書吊銷列表 Certification Revocation List)

是一種包含撤銷的證書列表的簽名資料結構。CRL是證書撤銷狀態的公佈形式,CRL 就像信用卡的黑名單,用於公佈某些數字證書不再有效。CRL是一種離線的證書狀態資訊。它以一定的週期進行更新。CRL 可以分為完全 CRL和增量 CRL。在完全 CRL中包含了所有的被撤銷證書資訊,增量 CRL 由一系列的 CRL 來表明被撤銷的證書資訊,它每次釋出的 CRL 是對前面釋出 CRL的增量擴充。基本的 CRL 資訊有:被撤銷證書序列號、撤銷時間、撤銷原因、簽名者以及 CRL 簽名等資訊。基於 CRL的驗證是一種不嚴格的證書認證。CRL 能證明在 CRL 中被撤銷的證書是無效的。但是,它不能給出不在 CRL中的證書的狀態。如果執行嚴格的認證,需要採用線上方式進行認證,即 OCSP認證。一般是由CA簽名的一組電子文件,包括了被廢除證書的唯一標識(證書序列號),CRL用來列出已經過期或廢除的數字證書。它每隔一段時間就會更新,因此必須定期下載該清單,才會取得最新資訊。

1.3.8 SCEP (簡單證書註冊協議)

基於檔案的證書登記方式需要從您的本地計算機將文字檔案複製和貼上到證書釋出中心,和從證書釋出中心複製和貼上到您的本地計算機。 SCEP可以自動處理這個過程但是CRLs仍然需要手工的在本地計算機和CA釋出中心之間進行復制和貼上。

1.3.9 PKCS7 (加密訊息語法(pkcs7)

是各種訊息存放的格式標準。這些訊息包括:資料、簽名資料、數字信封、簽名數字信封、摘要資料和加密資料。

1.3.10 PKCS12 (個人數字證書標準,Public Key Cryptography Standards #12)

包含了公鑰和私鑰的二進位制格式的證書形式,一般以 pfx 作為證書檔案字尾名。用於存放使用者證書、crl、使用者私鑰以及證書鏈,pkcs12 中的私鑰是加密存放的。

1.3.11 CER   一般指使用DER格式的證書

CER 證書一般是以 DER 二進位制編碼的證書,證書中沒有私鑰,以 *.cer 作為證書檔案字尾名。證書可以以 BASE64 編碼輸出,以Base64 編碼的證書證書中沒有私鑰,BASE64 編碼格式的證書檔案,也是以 *.cer 作為證書檔案字尾名。

1.3.12 CRT    證書檔案,可以是PEM格式

1.3.13 KEY   一般指PEM格式的私鑰檔案

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

在生成資料證書是使用者可選擇不同的加密方式對資料進行加密,常見的加密演算法可以分成三類,對稱加密演算法,非對稱加密演算法和Hash演算法。

2.1 對稱加密

在對稱加密演算法中,加密使用的金鑰和解密使用的金鑰是相同的。也就是說,加密和解密都是使用的同一個金鑰。因此對稱加密演算法要保證安全性的話,金鑰要做好保密,只能讓使用的人知道,不能對外公開。在對稱加密演算法中,加密和解密都是使用同一個金鑰,不區分公鑰和私鑰。

對稱加密演算法的優點在於加解密的高速度和使用長金鑰時的難破解性。假設兩個使用者需要使用對稱加密方法加密然後交換資料,則使用者最少需要2個金鑰並交換使用,如果企業內使用者有n個,則整個企業共需要n×(n-1) 個金鑰,金鑰的生成和分發將成為企業資訊部門的惡夢。對稱加密演算法的安全性取決於加密金鑰的儲存情況,但要求企業中每一個持有金鑰的人都保守祕密是不可能的,他們通常會有意無意的把金鑰洩漏出去——如果一個使用者使用的金鑰被入侵者所獲得,入侵者便可以讀取該使用者金鑰加密的所有文件,如果整個企業共用一個加密金鑰,那整個企業文件的保密性便無從談起。

常見的對稱加密演算法:DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES。
DES是一種分組資料加密技術(先將資料分成固定長度的小資料塊,之後進行加密),速度較快,適用於大量資料加密,而3DES是一種基於DES的加密演算法,使用3個不同密匙對同一個分組資料塊進行3次加密,如此以使得密文強度更高。
相較於DES和3DES演算法而言,AES演算法有著更高的速度和資源使用效率,安全級別也較之更高了,被稱為下一代加密標準。

2.2 非對稱加密

在非對稱加密演算法中,加密使用的金鑰和解密使用的金鑰是不相同的,也稱為公私鑰加密,也就是說加密使用的金鑰和解密使用的金鑰不同。

假設兩個使用者要加密交換資料,雙方交換公鑰,使用時一方用對方的公鑰加密,另一方即可用自己的私鑰解密。如果企業中有n個使用者,企業需要生成n對金鑰,並分發n個公鑰。由於公鑰是可以公開的,使用者只要保管好自己的私鑰即可,因此加密金鑰的分發將變得十分簡單。同時,由於每個使用者的私鑰是唯一的,其他使用者除了可以可以通過資訊傳送者的公鑰來驗證資訊的來源是否真實,還可以確保傳送者無法否認曾傳送過該資訊。非對稱加密的缺點是加解密速度要遠遠慢於對稱加密,在某些極端情況下,甚至能比非對稱加密慢上1000倍。

常見的非對稱加密演算法:RSA、ECC(移動裝置用)、Diffie-Hellman、El Gamal、DSA(數字簽名用)。
RSA和DSA的安全性及其它各方面效能都差不多,而ECC較之則有著很多的效能優越,包括處理速度,頻寬要求,儲存空間等等。

2.3 Hash演算法

Hash演算法特別的地方在於它是一種單向演算法,使用者可以通過Hash演算法對目標資訊生成一段特定長度的唯一的Hash值,卻不能通過這個Hash值重新獲得目標資訊。因此Hash演算法常用在不可還原的密碼儲存、資訊完整性校驗等。

常見的Hash演算法:MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1。
這幾種演算法只生成一串不可逆的密文,經常用其效驗資料傳輸過程中是否經過修改,因為相同的生成演算法對於同一明文只會生成唯一的密文,若相同演算法生成的密文不同,則證明傳輸資料進行過了修改。通常在資料傳說過程前,使用MD5和SHA1演算法均需要傳送和接收資料雙方在資料傳送之前就知道密匙生成演算法,而HMAC與之不同的是需要生成一個密匙,傳送方用此密匙對資料進行摘要處理(生成密文),接收方再利用此密匙對接收到的資料進行摘要處理,再判斷生成的密文是否相同。
加密演算法的效能通常可以按照演算法本身的複雜程度、金鑰長度(金鑰越長越安全)、加解密速度等來衡量。上述的演算法中,除了DES金鑰長度不夠、MD2速度較慢已逐漸被淘汰外,其他演算法仍在目前的加密系統產品中使用。

回到目錄 三、生成數字證書的方式

數字證書可以通過線上工具,指令碼程式碼,KEYTOOL工具,OPEN SSL工具等多種方式生成。下面以常用的RSA非對稱加密為例子,向大家介紹幾種常用的數字證書生成方式。

3.1 利用KEYTOOL工具生成數字證書

KEYTOOL 是個金鑰和證書管理工具,可以在 JAVA 環境下管理安全鑰匙與證書的生成與安裝。它還是一個有效的安全鑰匙和證書的管理工具,使使用者能夠管理自己的公鑰/私鑰對及相關證書。它管理一個儲存了私有鑰匙和驗證相應公共鑰匙的與它們相關聯的X.509 證書鏈的keystore(相當一個數據庫,裡面可存放多個X.509標準的證書)。能夠使使用者使用數字簽名來管理他們自己的私有/公共鑰匙對,管理用來作自我鑑定的相關的證書,管理資料完整性和鑑定服務,還能使使用者在通訊時快取它們的公共鑰匙。

3.1.1 KEYTOOL命令介紹

KEYTOOL通是以keytool開關,當中常用命令有: 

keytool -genkey -alias casserver -keypass cas123 -keyalg RSA -keystore casserver.keystore -validity 365
keytool -export -alias casserver -storepass cas123 -file casserver.cer -keystore casserver.keystore
keytool -import -trustcacerts -alias casserver -storepass cas123 -file casserver.cer –keystore cacerts
  • -genkey      在使用者主目錄中建立一個預設檔案".keystore",還會產生一個mykey的別名,mykey中包含使用者的公鑰、私鑰和證書
    在沒有指定生成位置的情況下,keystore會存在使用者系統預設目錄,如:對於window xp系統,會生成在系統的C:/Documents and Settings/UserName/檔名為“.keystore”
  • -alias       產生別名  -keystore 指定金鑰庫的名稱(產生的各類資訊將不在.keystore檔案中)  -keyalg  指定金鑰的演算法 (如 RSA  DSA(如果不指定預設採用DSA))
  • -validity    指定建立的證書有效期多少天-keysize     指定金鑰長度
  • -storepass   指定金鑰庫的密碼(獲取keystore資訊所需的密碼)
  • -keypass     指定別名條目的密碼(私鑰的密碼)
  • -dname       指定證書擁有者資訊
    例如:  "CN=名字與姓氏,OU=組織單位名稱,O=組織名稱,L=城市或區域名稱,ST=州或省份名稱,C=單位的兩字母國家程式碼"
  • -list        顯示金鑰庫中的證書資訊      
    例如: keytool -list -v -keystore 是指定 keystore -storepass 密碼 -v 顯示金鑰庫中的證書詳細資訊
  • -export      將別名指定的證書匯出到檔案  
    例如:keytool -export -alias 需要匯出的別名 -keystore 指定keystore -file 指定匯出的證書位置及證書名稱 -storepass 密碼
  • -file            引數指定匯出到檔案的檔名
  • -delete       刪除金鑰庫中某條目    
    例如:keytool -delete -alias 指定需刪除的別  -keystore 指定keystore  -storepass 密碼
  • -printcert   檢視匯出的證書資訊     
    例如:keytool -printcert -file leslie.crt
  • -keypasswd   修改金鑰庫中指定條目口令    
    例如:keytool -keypasswd -alias 需修改的別名 -keypass 舊密碼 -new  新密碼  -storepass keystore密碼  -keystore sage
  • -storepasswd 修改keystore口令      
    例如:keytool -storepasswd -keystore c:/leslie.keystore(需修改口令的keystore) -storepass 123456(原始密碼) -new 888888(新密碼)
  • -import      將已簽名數字證書匯入金鑰庫 
    例如: keytool -import -alias 指定匯入條目的別名 -keystore 指定keystore -file 需匯入的證書

3.1.2 生成 *.keystore 檔案流程

首先執行以下命令,分別輸入金鑰庫口令、姓名,單位,組織,城市,省份,國家等資訊,經確認後生成對應的 leslie.keystore 檔案。注意 *.keystore 檔案相當於一個資源庫,後面的公鑰、私鑰、證書等都依賴於它生成,必須謹慎保管。

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

提示:  -alias指定別名為 everygold; -keyalg 指定 RSA 演算法;-keypass 指定私鑰密碼為123456;
             -keystore 指定金鑰檔名稱為 leslie.keystore;-validity指定有效期為365天。

3.1.3 生成數字證書

根據上述生成的 leslie.keystore 檔案,執行以下命令就可以生成數字證書 leslie.cer

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

提示:  -alias 指定別名為 everygold; -storepass 指定私鑰為 123456;
            -file 指定匯出證書的檔名為 leslie.cer;-keystore 指定之前生成的金鑰檔案的檔名

注意: -alias 和- storepass 必須為生成 leslie.keystore 金鑰檔案時所指定的別名和密碼一致,否則證書匯出失敗

生成證書 

若需要獲取 BASE64 或 DER 證書,可以使用匯出功能,在圖片上按 “複製到檔案”,選擇檔案格式即可。

以文字格式開啟匯出的 BASE64 證書,可以看到

-----BEGIN CERTIFICATE-----
MIICRjCCAa+gAwIBAgIEIvzKsDANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD
TjELMAkGA1UECBMCR0QxCzAJBgNVBAcTAkdaMQ4wDAYDVQQKEwVwdWppbjEMMAoG
A1UECxMDU3VuMQ8wDQYDVQQDEwZMZXNsaWUwHhcNMTcwODI5MDMwMjE4WhcNMTgw
ODI5MDMwMjE4WjBWMQswCQYDVQQGEwJDTjELMAkGA1UECBMCR0QxCzAJBgNVBAcT
AkdaMQ4wDAYDVQQKEwVwdWppbjEMMAoGA1UECxMDU3VuMQ8wDQYDVQQDEwZMZXNs
aWUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKFVrCaKFi2GtJjyuWSPrJah
.........................
-----END CERTIFICATE-----

或者使用以下語句,也可檢視到匯出的證書

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

顯示結果與上述方法一致

3.2 指令碼程式碼生成證書

若對KEYTOOL工具不太熟悉的朋友 ,也可通過JAVA程式碼直接生成數字證書,原理與KEYTOOL生成的基本一致。

 1 public class CerTest {  
 2     public static void main(String[] args){
 3              CerTest test=new CerTest();
 4              //生成 keystore 檔案
 5              test.getKeyStore();
 6              //生成 *.cer 證書檔案
 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指定證書有效期(單位:天),這裡是365天  
43                 "365",  
44                 "-keysize",//     指定金鑰長度  
45                 "1024",  
46                 "-alias", // -alias指定別名,這裡是everygold 
47                 "everygold",  
48                 "-keyalg", // -keyalg 指定金鑰的演算法 (如 RSA DSA(如果不指定預設採用DSA))  
49                 "RSA",  
50                 "-keystore", // -keystore指定儲存位置,這裡是d:/leslie.keystore  
51                 "d:/leslie.keystore",  
52                 "-dname",// CN=(名字與姓氏), OU=(組織單位名稱), O=(組織名稱), L=(城市或區域名稱),  
53                             // ST=(州或省份名稱), C=(單位的兩字母國家程式碼)"  
54                 "CN=(leslie), OU=(everygold), O=(pujinwang), L=(Guangzhou), ST=(Guangdong), C=(CN)",  
55                 "-storepass", // 指定金鑰庫的密碼(獲取keystore資訊所需的密碼)  
56                 "123456",   
57                 "-keypass",// 指定別名條目的密碼(私鑰的密碼)  
58                 "123456",   
59                 "-v"// -v 顯示金鑰庫中的證書詳細資訊  
60         };  
61         execCommand(arstringCommand);  
62     }  
63   
64     /** 
65      * 匯出證書檔案 
66      */  
67     public void export() {  
68   
69         String[] arstringCommand = new String[] {  
70   
71         "cmd ", "/k",  
72                 "start", // cmd Shell命令  
73                 "keytool",  
74                 "-export", // - export指定為匯出操作   
75                 "-keystore", // -keystore指定keystore檔案,這裡是d:/leslie.keystore  
76                 "d:/leslie.keystore",  
77                 "-alias", // -alias指定別名,這裡是ss  
78                 "everygold",  
79                 "-file",//-file指向匯出路徑  
80                 "d:/leslie.cer",  
81                 "-storepass",// 指定金鑰庫的密碼  
82                 "123456"   
83         };  
84         execCommand(arstringCommand);  
85       
86     }  
87 }  

執行成功後,可獲取與3.1節相同的 leslie.keystore 檔案與 leslie.cer 數字證書。
若需要獲取 BASE64 或 DER 證書,也可使用與 3.1.3 節所述方式獲取 ,在此不再重複介紹。

3.3 利用線上工具獲取數字證書

如果覺得使用KEYTOOL或程式碼生成數字證書過於繁瑣,可以直接使用線上生成工具生成免費數字證書。一般線上生成的證書有效期為 3 個月到 1年,到期後需要續費或證書無效。以下是幾個常用的線上證書生成工具,由於用法比較簡單,在此不作詳細介紹。

回到目錄 四、獲取公鑰和私鑰

在第二節已經介紹過,在加密演算法中有對稱加密,非對稱加密,Hash演算法等幾類。在對稱加密演算法中,加密使用的金鑰和解密使用的金鑰是相同的,使用起來比較簡單。而公鑰與私鑰一般用於非對稱的加密方式,是安全性最高,使用最為頻密的加密方式,下面幾節,將為大家介紹一下非對稱加密的使用方式。
公鑰(Public Key)與私鑰(Private Key)是通過一種演算法得到的一個金鑰對(即一個公鑰和一個私鑰),公鑰是金鑰對中公開的部分,私鑰則是非公開的部分。公鑰通常用於加密會話金鑰、驗證數字簽名,加密資料可以用相應的私鑰進行資料解密。通過這種演算法得到的金鑰對能保證在世界範圍內是唯一的。使用這個金鑰對的時候,如果用其中一個金鑰加密一段資料,必須用另一個金鑰解密。比如用公鑰加密資料就必須用私鑰解密,如果用私鑰簽名則必須用公鑰驗籤,否則資料將不會成功生成。

由於使用 KEYTOOL 等工具無法直接匯出公鑰和私鑰,所以必須通過程式碼進行匯出。而公鑰和私鑰都是二進位制資料,所以一般 用Base 64 方式進行儲存。下面以上述有證書為例子,匯出對應的公鑰與私鑰。

  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金鑰庫(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訪問密碼
 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中獲取公鑰,並經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         * 獲取經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 }

輸出結果:

</div