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

引言html

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

 

 
目錄

1、數字證書介紹數據庫

3、生成數字證書的方式緩存

6、數字證書籤名與驗籤服務器

 
 
 
1、數字證書介紹
 

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/六、微軟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格式的私鑰文件

 
2、加密算法介紹

在生成數據證書是用戶可選擇不一樣的加密方式對數據進行加密,常見的加密算法能夠分紅三類,對稱加密算法,非對稱加密算法和Hash算法。

2.1 對稱加密

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

對稱加密算法的優勢在於加解密的高速度和使用長密鑰時的難破解性。假設兩個用戶須要使用對稱加密方法加密而後交換數據,則用戶最少須要2個密鑰並交換使用,若是企業內用戶有n個,則整個企業共須要n×(n-1) 個密鑰,密鑰的生成和分發將成爲企業信息部門的惡夢。對稱加密算法的安全性取決於加密密鑰的保存狀況,但要求企業中每個持有密鑰的人都保守祕密是不可能的,他們一般會有意無心的把密鑰泄漏出去——若是一個用戶使用的密鑰被入侵者所得到,入侵者即可以讀取該用戶密鑰加密的全部文檔,若是整個企業共用一個加密密鑰,那整個企業文檔的保密性便無從談起。

常見的對稱加密算法:DES、3DES、DESX、Blowfish、IDEA、RC四、RC五、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算法:MD二、MD四、MD五、HAVAL、SHA、SHA-一、HMAC、HMAC-MD五、HMAC-SHA1。
這幾種算法只生成一串不可逆的密文,常常用其效驗數據傳輸過程當中是否通過修改,由於相同的生成算法對於同一明文只會生成惟一的密文,若相同算法生成的密文不一樣,則證實傳輸數據進行過了修改。一般在數據傳說過程前,使用MD5和SHA1算法均須要發送和接收數據雙方在數據傳送以前就知道密匙生成算法,而HMAC與之不一樣的是須要生成一個密匙,發送方用此密匙對數據進行摘要處理(生成密文),接收方再利用此密匙對接收到的數據進行摘要處理,再判斷生成的密文是否相同。
加密算法的效能一般能夠按照算法自己的複雜程度、密鑰長度(密鑰越長越安全)、加解密速度等來衡量。上述的算法中,除了DES密鑰長度不夠、MD2速度較慢已逐漸被淘汰外,其餘算法仍在目前的加密系統產品中使用。

 

3、生成數字證書的方式

數字證書能夠經過在線工具,腳本代碼,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年,到期後須要續費或證書無效。如下是幾個經常使用的在線證書生成工具,因爲用法比較簡單,在此不做詳細介紹。

  1. Amazon Web Services (AWS) 是 Amazon.com 旗下的一個網絡雲服務站點
    address:https://aws.amazon.com/cn/?nc2=h_lg
  2. ChinaSSL是亞狐科技旗下專爲客戶提供數字證書、網絡安全服務的站點
    address:https://csr.chinassl.net/index.html
  3.  MySSL 則是亞洲誠信(TRUSTASIA)旗下專爲用戶提供網絡安全雲服務平臺
    address:https://myssl.com/csr_create.html

 

4、獲取公鑰和私鑰

在第二節已經介紹過,在加密算法中有對稱加密,非對稱加密,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 }

輸出結果:

爲方便保存,通常咱們會以Base64位方式把公鑰與私鑰存儲起來
publicKey.key 公鑰文件:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbUPe3WGFA0QPGCrPrXCUR7K7M
aZQY1btYZrAFjpT/k00zkj/AfcUeEZk6Tf+9mgvZ3KRVvSFaA9kYiVCJOjGfnW2H
fk6u7iOwSs/kwpC5uUzdoWlc5ZX7iC9SACXJgDg/T5HBRpXpsEkxhzWLUKy1FQDC
KduLuEFdzaO4XsSX7QIDAQAB
-----END PUBLIC KEY-----

privateKey.key 私鑰文件:

-----BEGIN PRIVATE KEY-----
MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBANtQ97dYYUDRA8YK
s+tcJRHsrsxplBjVu1hmsAWOlP+TTTOSP8B9xR4RmTpN/72aC9ncpFW9IVoD2RiJ
UIk6MZ+dbYd+Tq7uI7BKz+TCkLm5TN2haVzllfuIL1IAJcmAOD9PkcFGlemwSTGH
NYtQrLUVAMIp24u4QV3No7hexJftAgMBAAECgYEAkcm/8Yv5kimfFY3VzhXBuqmY
BOAGB4BEel5AkmEWoNIdVrPYVzAD0ZonPn/NCg+V4yvtveTsf7bhIJNfCum5Q8NL
V0YNn5+C1JMZoI9BrRXQjCH30Oy78QfHH9ATigDZ7cr/ke/0hJqO4hks++XlM6Oy
MIuoHy1WUTy5Hm3qbWECQQDvZFDixgwYwiyC9fzEj8NmWyINZx+Ny2DhnZKtKN6r
o7aplGfBPU9NZ/vLQk7AZPS+24hhu7CYlOUhhhoQjWr1AkEA6ogaMAQfPslyrl1W
R2KkPEOVbSSy4IJ5ZIBeJCDisgEtLb9EZ4JzXIfN6usyiJNtwf5k04zEkWBz1f5r
mtTOGQJBAMSodkI1TA6yxPo4thOLvovBZfH4u1UytD3jwnD52CLMdOxOfAWlJhaC
y7iomiU3Sk/X7OvM0kAmYSzvC055vlkCQQDOR0sRNG7u4Gv3pKyAOOhPAPpqdr7F
7LwsgyNKD4qUGajM9c+KYxhoKCIbHybhLRp6Z+/yiXtSik0XyKCIG+fxAkEAsdlz
YkpcG6T38wC0px+Mhq06AIhEF3sy3wLbM3d4ABlNMj3HqlHMPtvCV1L3dpc/8y89
dAPu9OiHf8nyar9eVQ==
-----END PRIVATE KEY-----

如今 *.keystore 、*.cer 證書、Base64 證書、公鑰文件 public.key 私鑰文件 private.key 都已成功生成,下面的章節將爲你們介紹數據加密、數據解密、數字簽名、數字驗籤的使用方式。但在此以前,我想先爲你們講解一下它們的概念與應用場景。
記得在第二節曾經向你們介紹過對稱加密與非對稱加密的區別,因爲對稱加密的加密與解密的密鑰都是一致,加密解密雙方都同時擁有密鑰,容易形成密鑰的泄露。因此通常企業在不一樣的業務流程下都會使用不一樣的密鑰,以防數據被泄露。但在大型的企業中,若使用對稱加密這種方式,企業將會產生大量的密鑰,難於管理並且安全性難以保障,並不可取,因此就產生了非對稱加密方式。
非對稱加密的狀況下,在企業須要獲取客戶端數據時,能夠把公鑰向客戶端公開,數據進行加密後,就算加密數據被涉取,在沒有私鑰的狀況,數據內容都不會被破解,確保了數據的安全性。這時,只要企業保證私鑰的保密前提下,一個公鑰能夠向多個客戶端進行公開用做數據傳輸加密。
而數字簽名的應用場景有點相反,數字簽名是企業爲客戶端確認數據來源的準確性而提供的服務。通常應用於政府機關、行政部門、金融行業、資訊行業等企業的數據發佈上。數據都是由企業經過私鑰進行簽名,只要客戶端擁有對應的公鑰,就能夠對數據進行驗籤。只要驗籤成功,就能證實該數據是來源此數字證書所屬的企業,以保證數據來源的可靠性。通常在國家政策的發佈,企業數據的公開,經濟數據的公開等場景下應該最爲普遍。

 

5、數字證書加密與解密
 
通過上面的介紹,你們應該瞭解到數據加密、數據解密、數字簽名、數字驗籤的使用場景。
下面將爲你們介紹數據加密與解密方式:
  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      * 使用公鑰加密數據
 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         // 對數據加密
 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      * 使用私鑰解密數據
 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轉碼解密私鑰
 61         byte[] pk = Coder.decryptBASE64(privateKey);
 62         // BASE64轉碼解密密文
 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         // 對數據加密
 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算法 公鑰加密隨機數
 96             String secretText = MyCoder.encryptByPublicKey(strPublicKey, originalText);
 97             System.out.println("\n經RSA公鑰加密後 = " + secretText);
 98             System.out.println("\n經RSA公鑰加密後長度 = " + secretText.length());
 99             
100             String text = MyCoder.descryptByPrivateKey(strPrivateKey, secretText);
101             System.out.println("\n經RSA私鑰解密後 = 【" + text + "】");
102             System.out.println("\n經RSA私鑰解密後長度 = 【" + text.length() + "】");
103             
104         } catch (Exception e) {
105             e.printStackTrace();
106         }
107     }
108 }

測試結果

固然,若是公鑰和私鑰已經保存在 public.key 與 private.key 文件裏,就能夠直接從文件讀取,無須再經過 *. keystore 文件獲取。
 
6、數字證書籤名與驗籤

上面介紹過簽名與驗籤主要用於政策機關,金融機構,權威信息網站對外公報信息時使用。
通常使用場景下,簽名與驗籤每每會與加密解密同時使用,企業會生成兩對密鑰,一對用於對企業正式的註冊名稱進行簽名,另外一對用於詳細數據的加密。客戶驗籤後就可證實信息來源的真確性,而後再對詳細信息進行解密。
簽名與驗籤代碼以下:

 1 public class MySign {
 2     /*
 3     * @param keyStorePath 密鑰庫存儲路徑
 4     * @param alias 密鑰庫別名
 5     * @param password 密鑰庫密碼
 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      * 生成數據簽名
30      * @param data 源數據
31      */
32     public static byte[] sign(byte[] data) 
33             throws Exception {
34         // 得到證書
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         // 構建簽名
41         Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
42         signature.initSign(privateKey);
43         signature.update(data);
44         return signature.sign();
45     }
46     
47     /*
48      * 生成數據簽名並以BASE64編碼
49      * @param data 源數據
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      * 對二進制數據進行驗籤
59      * @param data 已加密數據
60      * @param sign 數據簽名[BASE64]
61      */
62     public static boolean verifySign(byte[] data, String sign) 
63             throws Exception {
64         // 得到證書
65         X509Certificate x509Certificate = (X509Certificate) getCertificate();
66         // 得到公鑰
67         PublicKey publicKey = x509Certificate.getPublicKey();
68         // 構建簽名
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      * 對String數據進行驗籤
77      * @param data 字符串
78      * @param sign 數據簽名[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="驢友的天空俱樂部";
92         String base64=MySign.signToBase64(sign);
93         System.out.println("簽名爲:"+sign+"\n\n簽名後數據:\n"+base64);
94         boolean isRight=MySign.verifySginString(sign,base64);
95         System.out.println("\n驗簽結果:"+isRight);
96     }
97 }

輸出結果

 

 
本章小結

文章簡單介紹了數字證書的生成使用過程,*.cer 證書的導出,公鑰 public.key,私鑰private.key 的導出等功能,但對於數字證書的功能,本文介紹的可說只是冰山一角。通常在政府型項目、大型的金融項目、B2B/B2C/P2P商業網站,數字證書的使用是比較常見。特別是在手機APP流行的今天,數字證書的使用更是愈來愈普及化。但願本文對各位對數據證書的理解有所幫助。

對 .NET  開發有興趣的朋友歡迎加入QQ羣:230564952 共同探討 !
對 JAVA 開發有興趣的朋友歡迎加入QQ羣:174850571 共同探討 !

 

服務類工具的應用與管理

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

Windows Server 2008 R2 負載平衡入門篇

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

 

做者:風塵浪子

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

原創做品,轉載時請註明做者及出處

相關文章
相關標籤/搜索