SSL與CA

某項目的業務系統要求在用戶使用的過程使用數字證書。在剛接手這個任務時,我對箇中的知識幾乎不瞭解,於是到處搜刮相關資料,網上此類文章甚多,但都比較零散,而且個人認爲其中絕大部分未能盡釋所疑。在經歷了數天的鬱悶及實踐以後,終有所悟,作此文以記。

1          對稱加密與非對稱加密

對稱加密方法的加密與解密採用相同的密鑰,因此任何人只要獲得其中的密鑰,就可以對密文進行解密。而非對稱加密方法有兩個不同密鑰,任意一個都可以成爲加密密鑰,另外一個就是解密密鑰,用一個密鑰加密的密文必須用另一個密鑰纔可以解密。


2          公鑰與私鑰

在非對稱加密方法的兩個密鑰中,保管其中一個密鑰,禁止泄漏他人,除了密鑰擁有者以外,任何人都不知道,此即私鑰。另一個密鑰則公之於衆,任何人都可以獲得,此即公鑰。可知,用私鑰加密的密文必須用公鑰解密,反之亦然。


3          數字簽名

數字簽名是基於非對稱加密方法來實現的。擁有私鑰的一方使用私鑰對某一份內容加密後發送給其他人(個體或羣休),因爲任何人都可以擁有與該私鑰對應的公鑰,擁有公鑰者使用公鑰對接收到的密文進行解密,如果能正確解密,則說明此份內容必然是擁有私鑰的一方發出。另一方面,如果擁有公鑰的實體希望把一份內容發送給擁有私鑰的一方而不希望其它任何人看到,則可以利用該公鑰加密此份內容。因爲只有私鑰擁有者纔可以將密文解密,所以能保證任何其他人無法查看其內容。


4          數字證書

數字證書是以數字簽名的方式通過第三方權威認證機構有效地進行網上身份認證,以幫助各個實體識別對方身份及表明自身身份的證書,具有防抵賴功能及真實、安全、保密和防篡改的特性。在此,我們最主要的是需要知道數字證書是一個文件,該文件保存了某個實體(個人、機構或設備等)的信息及該實體所擁有私鑰對應的公鑰。


5          SSL協議這裏

主要介紹SSL握手協議以建立安全通信通道的過程。


1)        客戶端的瀏覽器向服務器傳送客戶端 SSL 協議的版本號,加密算法的種類,產生的隨機數,以及其他服務器和客戶端之間通訊所需要的各種信息。

2)        服務器向客戶端傳送 SSL 協議的版本號,加密算法的種類,隨機數以及其他相關信息,同時服務器還將向客戶端傳送自己的證書。

3)        客戶利用服務器傳過來的信息驗證服務器的合法性。服務器的合法性包括:證書是否過期,發行服務器證書的 CA 是否可靠,發行者證書的公鑰能否正確解開服務器證書的“發行者的數字簽名”,服務器證書上的域名是否和服務器的實際域名相匹配。如果合法性驗證沒有通過,通訊將斷開;如果合法性驗證通過,將繼續進行第4)步。

4)        客戶端隨機產生一個用於後面通訊的“對稱密碼”,然後用服務器的公鑰(服務器的公鑰從步驟2)中的服務器的證書中獲得)對其加密,然後將加密後的“預主密碼”傳給服務器。

5)        如果服務器要求客戶的身份認證(在握手過程中爲可選),用戶可以建立一個隨機數然後對其進行數據簽名,將這個含有簽名的隨機數和客戶自己的證書以及加密過的“預主密碼”一起傳給服務器。

6)        如果服務器要求客戶的身份認證,服務器必須檢驗客戶證書和簽名隨機數的合法性。具體的合法性驗證過程包括:客戶的證書使用日期是否有效,爲客戶提供證書的 CA 是否可靠,發行 CA 的公鑰能否正確解開客戶證書的發行 CA 的數字簽名,檢查客戶的證書是否在證書廢止列表(CRL)中。檢驗如果沒有通過,通訊立刻中斷;如果驗證通過,服務器將用自己的私鑰解開加密的“預主密碼”,然後執行一系列步驟來產生主通訊密碼(客戶端也將通過同樣的方法產生相同的主通訊密碼)。

7)        服務器和客戶端用相同的主密碼即“通話密碼”,一個對稱密鑰用於 SSL 協議的安全數據通訊的加解密通訊。同時在 SSL 通訊過程中還要完成數據通訊的完整性,防止數據通訊中的任何變化。

8)        客戶端向服務器端發出信息,指明後面的數據通訊將使用的步驟7)中的主密碼爲對稱密鑰,同時通知服務器客戶端的握手過程結束。

9)        服務器向客戶端發出信息,指明後面的數據通訊將使用的步驟7)中的主密碼爲對稱密鑰,同時通知客戶端服務器端的握手過程結束。

10)     SSL 的握手部分結束,SSL 安全通道的數據通訊開始,客戶和服務器開始使用相同的對稱密鑰進行數據通訊,同時進行通訊完整性的檢驗。

6          從何處獲得證書

基本的原理差不多就這些,下一個問題是從哪裏獲得數字證書?從前面的SSL握手過程可以知道,客戶端需要查看服務器的證書,以證明服務器的身份,而服務器端也要(當然這需要服務器有相關的配置)查看客戶端證書以證明客戶的身份。因此我們至少需要兩個證書:服務器證書和客戶證書。事實上,每一個客戶都可以擁有自己的證書以證明自己的身份。當一個實體需要一個證書的時候,需要向相關的權威認證機構申請,比如GDCA,由該權威機構向該實體頒發證書。所謂權威機構就是已經被另一個權威機構證明是真實有效的機構,因此這是一個遞歸的過程,在最頂層有一個虛擬的根機構,被稱爲RootCA。申請證書需要一定的費用,根據證書類型的不同而不同,從GDCA的網站上得知,個人證書是50元/年,而網站證書則需要10000元/年。如果申請一個有效其爲10年的證書,這是一筆不小的費用。那麼能不能不申請而獲得證書呢?


7          自己做CA

首先要說明,不管你的證書是由哪個機構頒發的,對於通信過程來說都是安全的。因此對於某個特定範圍的圈子來說,完全可以由該圈子中公認的機構做CA。對於一個企業來說,企業及其客戶所組成的圈子中,企業可以認爲是具有權威性的,於是就可以作爲一個權威機構向其客戶頒發證書。據瞭解,廣東發展銀行及中國建設銀行客戶所用的數字證書就是該銀行頒發的。在這裏需要使用一個軟件openssl。Openssl的功能相當強大,偶對其中的功能也不甚瞭解,只瞭解其中與CA認證相關的部分功能,基本上可以滿足自己做CA的要求。在使用openssl前,先要設置一個環境變量OPENSSL_CONF,使其指向openssl安裝目錄下的openssl.cnf文件。產生證書的過程大致爲:生成密鑰對->生成簽證請求->簽證。簽證後的證書就爲數字證書,其中保存有對應實體的公鑰信息。


下面是使用opensll實現CA並簽發證書的過程:

1)        生成CA密鑰

CA作爲一個權威機構,他本身也是使用證書來標識自己,CA本身也擁有私鑰。在簽發數字證書的過程中,CA的私鑰主要用於加密用戶證書請求中的用戶信息及公鑰。genrsa -out cakey.pem 1024該命令會產生長度爲1024字節的私鑰文件cakey.pem。


2)        生成CA證書請求req -new -out careq.csr -key cakey.pem此命令會根據cakey.pem產生該證書的請求文件careq.csr。

3)        用CA私鑰自簽名x509 -req -in careq.csr -out cacert.pem -signkey cakey.pem -days 3650該命令會根據輸入的證書請求及CA私鑰,生成CA證書。至此,作爲CA所要求的證書已經準備好,所得到的cakey.pem可用於將來頒發證書,而cacert.pem證書作爲用戶的可信任證書,需要分發給每一個由該CA機構頒發證書的實體。

8          服務器證書與客戶端證書的製作服務器證書與客戶端證書的製作稍有不同,這是由於服務器對證書格式與客戶端證書格式要求不同導致的。對於Tomcat或WebSphere這樣的服務器(偶只知道這兩種),通常都要求一種JKS格式的文件,在該文件中,保存有服務器私鑰、服務器證書以及服務器根證書鏈(從RootCA一直到服務器證書頒發機構的一系列CA證書列表)。

8.1          服務器證書要製作這一類證書,需要使用JDK提供的一個工具keytool。

下面是使用keytool製作證書庫的過程:

1)        生成初始密鑰庫keytool -genkey -alias serveralias -keystore server.jks -keyalg RSA輸入keystore密碼:changit您的名字與姓氏是什麼?  [Unknown]:  CN您的組織單位名稱是什麼?  [Unknown]:  OU您的組織名稱是什麼?  [Unknown]:  O您所在的城市或區域名稱是什麼?  [Unknown]:  L您所在的州或省份名稱是什麼?  [Unknown]:  ST該單位的兩字母國家代碼是什麼  [Unknown]:  CNCN=CN, OU=OU, O=O, L=L, ST=ST, C=CN 正確嗎?  [否]:  y 輸入證書的主密碼        (如果和 keystore 密碼相同,按回車):在輸入上述的“名字與姓氏”時,要注意所輸入的值應該與服務器的IP或域名一致,否則在客戶端驗證服務器證書時會認爲該證書與指定的服務器實體不匹配,如果是IE就會彈出一個窗口提示用戶是否信任該證書。

2)        生成證書請求keytool –certreq -alias serveralias -sigalg MD5withRSA -file server.csr -keypass changeit -keystore  server.jks -storepass changeit最後生成的證書請求文件爲server.csr。把該請求發送給證書頒發機構,該機構將會驗證證書請求中的實體信息,然後實現簽證。因爲我們是自己做CA,所以簽證這一步也是我們自己來做。

3)        實現簽證簽證仍然使用openssl,而不是keytool。在openssl中,輸入以下命令:x509 -req -in server.csr -out servercert.pem -CA cacert.pem -CAkey cakey.pem -days 3650輸出的servercert.pem文件即是簽證後的證書,即證書請求響應。命令中用到的cakey.pem和cacert.pem是上面生成的CA密鑰文件和CA根證書。完成CA簽證後,把證書請求響應連同CA根證書一起返回給申請者。申請者需要把CA根證書(鏈)及證書請求響應導入到JKS庫中。此時使用的工具是keytool。keytool –import –trustcacerts –keystore server.jks –file cacert.jks –alias RootCAkeytool –import –trustcacerts –keystore server.jks –file servercert.jks –alias serveralias需要注意的是,首先導入CA根證書(鏈),最後才導入證書請求響應,而且導入證書請求響應時的別名必須與生成JKS庫時使用的別名一致。至此,服務器端的JKS文件已經完成,可以配置到相應的服務器中。

8.2          客戶端證書至於客戶端證書,既可以用openssl製作,也可以用keytool來製作,不過用keytool來生成的話,要麻煩一些,而且簽證的步驟必須由opensll來實現,因此這裏講述用openssl生成客戶端證書的過程。

1)        生成客戶端密鑰文件genrsa -out clientkey.pem 1024該命令會產生clientkey.pem密鑰文件。

2)        產生證書請求req -new -out clientreq.csr -key client-key.pem把證書請求發送給CA以實現簽證,這裏同樣由自己做。

3)        實現簽證x509 -req -in clientreq.csr -out clientcert.pem -signkey clientkey.pem -CA cacert.pem -CAkey cakey.pem -CAcreateserial -days 3650簽證後的客戶端證書只包含了客戶端的公鑰及客戶實體的信息,不包含私鑰。

4)        生成客戶端可導入的客戶端證書pkcs12 -export -clcerts -in clientcert.pem -inkey clientkey.pem -out client.pfx這一步把客戶端的證書(公鑰)與私鑰捆綁在一起,生成client.pfx文件,該文件連同CA根證書一起發送給客戶。

9          配置IE客戶端對於使用IE的客戶,需要把CA根證書及個人證書導入到IE的證書列表中。在導入CA根證書的時候,如果不是權威的CA根證書(自己當CA的那種),IE會提示是否信任該證書,確認後CA根證書會保存在證書信任列表中。此後再導入客戶自己的證書,IE將會認爲這是可信的,因爲CA根證書保存在證書信任列表中了。在導入含有私鑰的客戶證書時,IE會提示是否給私鑰加密以及設置私鑰是否可導出等屬性,建議把私鑰加密並設置爲不可導出,並要求每次使用證書時輸入密碼。

10      配置WebSphere服務器使用數字證書(憑記憶描述)打開WebSphere的管理控制檯,進入到安全性->SSL頁面中,該頁面列出了目前所有的SSL配置庫,一般來說只有一個默認配置庫,我們修改該配置庫的參數即可。點擊默認的配置庫鏈接,將含有服務器證書的密鑰庫路徑及密碼,修改信任CA列表的密鑰庫路徑(一般來說可與服務器證書的密鑰庫一致)及密碼,選中 “客戶機認證”選擇框即完成配置。

11      配置Apache使用數字證書(從別處參考)

11.1       編輯Apache的ssl.conf1)        指定服務器證書位置SSLCertificateFile <path-to-certificates>/servercert.pem2)        指定服務器證書key位置 SSLCertificateKeyFile <path-to-certificates>/serverkey.pem3)        證書目錄SSLCACertificatePath <path-to-certificates>4)        根證書位置SSLCACertificateFile <path-to-certificates>/cacert.pem 5)        開啓客戶端SSL請求 SSLVerifyClient require SSLVerifyDepth  1

11.2       啓動ssl apachectl startssl 會要求輸入server.key的密碼

12      在服務器端讀取客戶端發送的數字證書在某些情況下希望用戶使用數字證書時能夠自動登錄系統,這就需要以用戶的數字證書序列號作爲登錄標識。下列代碼演示在服務器端讀取客戶端數字證書的方法(Tomcat或WebSphere)。javax.servlet.request.X509Certificate[]  certs  = (javax.servlet.request.X509Certificate[])  request.getAttribute(“javax.servlet.request.X509Certificate”);if(certs!=null){       //第一個證書爲用戶個人證書javax.servlet.request.X509Certificate cert=( javax.servlet.request.X509Certificate)certs[0];//以16進制形式打印其序列號System.out.println(cert.toString(16)); }elseSystem.out.println(“could not get certificate from client!”);上傳的數字證書有數個,包括用戶個人證書及其根證書鏈,第一個爲用戶個人證書,接着爲用戶個人證書的根證書,再接着爲用戶個人證書根證書的根證書,依次類推。上述代碼是網上可以找到的代碼,而且可以正常通過編譯,但在實踐的過程中,偶發現javax.servlet.request.X509Certificate應該爲java.servlet.request.X509Certificate,否則會引發類型轉換異常。不知道這是不是服務器版本不同引起的問題,測試時使用的服務器版本爲WebShpere5.0.1。對於使用其它服務器或語言的情況,在網上可以找到很多例子,偶還沒有使用或測試過,不敢罔言。

13      後記CA認證的配置過程事實上並不複雜,重要的是一些基本概念的理解。開始的時候,由於缺乏相關的知識及經驗,走了不少的彎路,浪費不少時間,特撰此文,以啓後來者。撰寫過程中,引用了不少他人的文章,由於記錄零散,作者無從考究,在此對這些作者一併表示感謝。我已經盡力把事情說得清楚明白,但由於表達能力問題,文中不妥之處肯定不少,給你的閱讀及理解造成障礙。如果這樣,請你告訴我,我定當盡力改進。如果因此而提高我的表達能力,那將是我最大的榮幸。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章