為什么需要證書
- 實現了公鑰和私鑰的相互驗證,但是任何人都可以生成很多的密鑰對,密鑰對并沒有關聯實體身份,因此誕生可數字證書
- 前提是CA是所有用戶都信任的
- 用戶需要將自己的信息和公鑰交給CA進行認證生成一個屬于自己并被其與用戶認可的數字證書,然后雙方通信的時候使用與數字證書里面對應的公鑰進行數字簽名
證書生命周期
證書申請
- 證書的聲明周期是指證書申請到證書被吊銷整個過程,這個過程中涉及到證書的申請、頒發、使用和其余各個管理方面的問題
- 最常用的是RSA密鑰和DSA密鑰,算法的類型和具體的使用場景相關,比如用于密鑰交換目的的證書就不可以使用DSA密鑰,只能使用RSA密鑰
- 生成密鑰對可以使用OpenSSL的genrsa和gendsa命令,還可以使用req指令
- 申請的時候需要涉及到 用戶需要填寫哪些信息 以及如何對填寫的信息進行格式化操作
- PKCS#10標準規定了這些相關的格式。其基本思想是用戶根據要求填寫這些信息,然后將這些信息和用戶產生的公鑰一起用相應的私鑰簽名發給CA驗證,這可以使得CA確認這些信息是申請的用戶自己發送的,因為CA可以把證書請求中的公鑰拿出來驗證這個證書請求的簽名。
- OpenSSL提供了req指令幫助我們填寫和生成這個格式復雜的證書請求,當然,根據不同CA的要求,你可能需要更改OpenSSL的配置文件(默認是openssl.cnf)中證書請求相關的部分配置。完成這些工作,你就可以把證書請求交給CA,OpenSSL的CA指令,執行操作只要幾秒到幾百毫秒
證書頒發
- 第一步就是驗證證書請求上的簽名是否正確,也就是說,確保公鑰對應的私鑰就在申請者手中并且申請信息是正確的沒有被更改的。然后就要仔細審查證書請求里的用戶信息,這工作一般由CA管理人員完成,管理人員應該依據管理規范(一個正規的CA運營商應該具備的基本條件)對這些用戶信息進行審查和核實,必要的時候甚至需要親自查訪用戶等。CA可能對某些信息還有特殊要求,比如要求國家名字必須跟CA本身設定的一樣,或者要求省份跟CA設置的一樣,這些要求通常不需要人工審查,計算機程序可以比我們做得更好。OpenSSL通過設置OpenSSL配置文件(默認是opensl.cnf)的匹配策略來對這些字段提出不同的要求,這種策略通常有三種:匹配、支持和可選。匹配也就是要求申請填寫的信息跟CA設置信息必須一致,支持是指必須填寫這項申請信息,可選就靈活多了,可有可無。如果通過了所有這些嚴格的審查措施,那么CA就可以給你簽發證書了,如果CA是建立在OpenSSL指令的基礎上,那么其使用的簽發指令可能是ca,也可能是x509,但更可能是ca指令,因為它本身就是OpenSSL的一個模擬CA。
證書驗證
- 有了一個證書后你就可以在數字世界中必要的時候隨時出示這個證書證明你的身份。但是拿到你證書的人當然不會看一眼就信任你的證書,它需要仔細驗證你的證書,需要驗證的信息包括:CA的數字簽名、證書的有效期、證書是否被吊銷及其他一些可能的限制選項。在證書驗證過程中出現的一個問題是,這個需要驗證你的證書的用戶是否具備驗證你的證書的能力?如果用戶自己具備驗證能力和驗證所需要的材料,就可以自己驗證,比如使用OpenSSL的verify程序完成驗證過程。如果用戶自己沒有能力或者沒有足夠的資料進行驗證,那么可以到CA或者CA指定的機構驗證證書,在線證書服務協議(OCSP)規定了相應的規則,OpenSSL也提供了ocsp指令完成相應的功能。需要說明的是,上面的流程只是完成了對一個數字證書合法性的驗證,而并沒有驗證聲稱擁有這個證書人的真實身份。要進行這樣的驗證,需要具體的協議細節,但不管什么協議,驗證一個實體是否確實是其生成的證書對應的用戶都是基于證書內容里面包含的公鑰和相應的私鑰的基礎上的。
- 驗證方式:自行驗證 或者 借助CA平臺進行驗證
證書吊銷
- 在某些情況下,比如一個公司員工離開了原來的公司,那么他所擁有的證書也應該及時被撤銷,以防止該員工可能利用原有的權限獲取非法的信息。證書撤銷的操作從技術上來說包括兩個方面:一是從CA的證書數據庫中刪除被吊銷的證書;二是對外公布被撤銷的證書信息,如序列號等,具體來說就是生成和公布證書吊銷列表CRL。如果你使用的是OpenSSL的ca指令作為CA中心服務程序,那么可以使用ca指令的revoke選項和gencrl選項實現這些證書吊銷的操作。
證書過期
- 證書的使用有一定的期限,這是為了確保證書安全性和有效性的需要。證書過期后,CA需要更新證書庫中已經過期的證書的狀態,比如對過期證書歸檔和將其從有效證書庫中刪除等操作。如果使用OpenSSL的ca指令,那么需要使用updatedb選項更新證書庫中證書的標記狀態
證書的封裝類型
X.509證書
- X.509證書包含的內容主要是用戶信息、證書序列號、簽發者、有效期、公鑰、其他信息及CA的數字簽名,這些在公鑰基礎設施部分已經作了介紹。我們需要確認的是,X.509只包含了一個公鑰,而沒有這個公鑰對應的私鑰的任何信息。公鑰是可以公開的,所以X.509證書一般也是隨意公開的,任何人都可以獲取你的X.509證書,然后使用它來跟你通信。
- 比如在SSL協議中,在服務器要跟你建立安全信道的時候,就會給你發送它自己的X.509證書,以便證明自己的身份,這是必要的,也是安全的,它不用擔心你會利用它的X.509冒充它欺騙其他用戶,因為你沒有X.509證書里面公鑰相應的私鑰,達不到這樣的目的。
- X.509證書適用于一般的證書應用模式。Windows平臺對X.509證書是認可的,如果要在Windows平臺查看和管理X.509證書,需要將X.509證書文件后綴名改成cer、der或者crt之一。OpenSSL從來不會從文件名稱這些表面上的東西判斷一個證書的格式,它對X.509證書的支持是基于其文件內容的,一般來說,PEM編碼和DER編碼都是可以被接受的。并且,OpenSSL本身的ca指令頒發的證書就是X.509標準格式的。
PKCS#12證書
- 如果你的證書是使用OpenSSL或其他產品申請的,而不是使用微軟自身的KeyStore生成密鑰對并在線申請的,那么要在IE或IS服務器上使用該證書,你就得想辦法把證書和相應的私鑰關聯起來,并讓微軟的軟件認可它們之間的關聯關系。這時候你需要使用的就不僅僅是一個X.509證書,而是X.509證書和它相應的私鑰。
- 還有另外一種情況。一般來說,證書相應的私鑰應該保存在硬件設備中,如SmartCard和USBKey以確保其安全性,計算機存儲總是讓人不放心。但是很多時候由于條件限制或者安全性要求不足以讓單位的決策者掏出這么一筆錢買這些設備,那么就必須把證書和其相應的私鑰保存在內存中,這就對證書和私鑰的存放提出了復雜的要求。你可能需要在不同的計算機上使用相同的證書,當然,也需要相應的私鑰,如果把它們保存在不同的文件中,有可能因為弄錯了多個證書和私鑰之間的對應關系而導致沒有辦法使用,所以最好是把它們保存在一起。PKCS#12格式證書就是為了適應上述的這些需求產生的,它將證書和其相應的私鑰封裝在一起。當然,證書和私鑰需要的安全性是不一樣的,證書可以公開,所以不需要加密保存;而私鑰的安全性非常重要,PKCS#12采用了PKCS#8的私鑰封裝格式對私鑰進行了基于口令的加密,雖然這種安全性很值得懷疑,但是畢竟有了一些保護。如果你把證書和私鑰封裝成PKCS#12格式的證書,你就可以直接把它導入到微軟的平臺使用(比如IE),當然,最好之前把文件后綴名改成pfx或者p12。OpenSSL的所有指令幾乎都接受PKCS#12的格式,并且不計較你用什么文件名或者后綴名。同時,OpenSSL還給出了將X.509證書和其私鑰轉換成PKCS#12格式證書的指令pkcs12,該指令也能實現反向的功能,即將一個PKCS#12的證書轉換成一個X.509證書和一個私鑰。
PKCS#7證書
- 如果你使用的是一個根CA頒發的證書,驗證不會有太大的問題,你只要簡單把你和你的CA證書發送給驗證方就可以了,并且通常來說,驗證方甚至已經有了跟你相同的CA證書,驗證可能輕而易舉完成了。但是如果給你頒發證書的CA不是根CA情況就顯得復雜得多,如圖所示,你和你的驗證用戶可能隸屬于不同的CA,但是這些不同的CA可能屬于相同的根CA,那么驗證就需要更多的信息,不僅僅需要你的CA證書,還需要簽發你的CA證書的上級CA證書,直到上溯到根CA證書,也就是說,驗證的時候,驗證方會需要一個完整的證書鏈。所謂證書鏈,就是一個用戶證書和一系列與其證書相關的CA證書的有序集合。所以,考慮到用戶這些需求,為了使證書用戶能夠正確地使用自己的證書,CA在給用戶頒發證書的時候,不僅僅要給用戶發放用戶自己的證書,還可能需要把證書鏈中的所有CA證書都給用戶。
- ?上面所說的驗證過程對于一般情形來說還太理想了,事實上,一個CA或多或少會有一些由于各種原因被吊銷的證書(除非剛剛建立的CA),這些證書可能依然在有效期內,用戶驗證證書通常可能不使用OCSP協議(至少該協議不總是可行的),那么為了排除這些已經被吊銷的證書,就需要通知用戶那些證書已經無效,這一般通過證書吊銷列表(CRL)來實現。CRL是公開的,可以自由下載,但是很多時候驗證方可能要求用戶給它提供合法的CRL。這樣一來,用戶需要給驗證方提供的東西就非常多了:自己的證書、證書鏈上所有的CA證書和CRL。這么多東西如果一個一個地發送給接收方,他可能會煩死,因為他必須一一鑒別你發送過來的是什么東西,以及考慮怎么保存這些信息。為了避免上述所有這些尷尬的情況,PKCS#7標準的證書格式出現了。PKCS#7標準很簡單:可以包含多個證書和CRL。這樣就可以解決上述的問題了,在驗證的時候,把自己的證書、相關證書鏈上的CA證書和CRL封裝成一個PKCS#7格式證書發送給驗證方就可以了。微軟對PKCS#7證書的支持依賴文件后綴名p7,OpenSSL對PKCS#7協議的支持有限,但是提供了將普通用戶證書和CRL封裝成PKCS#7證書的指令crl2pkcs7,同時也提供了pkcs7指令來處理PKCS#7證書的一些相關問題。表列出了上述三種證書的基本情況。事實上,還有其他一些適應不同需要的證書封裝格式,但因為使用得不多,這里不再介紹。
?證書使用
- 使用數字證書的目的只有一個,在數字世界建立一個跟現實世界完全相類似的信任模型。數字證書的作用很簡單,幾乎就是跟現實世界的證書(比如身份證)作用一一對應的。現實世界中的身份證是怎么使用的呢?我們下面的介紹會將數字世界對應于現實世界的名字在括號中標出。首先,公安局(CA)頒發了你的身份證(數字證書),然后你要別人確認你的身份的時候,你拿出你的身份證,對方如果相信自己具備驗證身份證真偽的能力,那么他就會通過查看公安局蓋章(CA簽名)、你的資料信息(用戶主體信息)和其他信息來確認身份證是公安局頒發的還是偽造的。當然,如果這些都通過了,他可能還拿出一份公安局公布的無效身份證的資料(CRL)對照一下,看看你的身份證號碼(證書序列號)是不是已經名列其中了。如果你是一個守法的人,這樣的驗證可能很順利就通過了。但是也有可能用戶覺得事關重大,根本就不相信自己現有的能力和資料能夠確保身份證的合法性,那么他就需要把身份證拿到公安局或者公安局指定的某個代理機構(OCSP)確認身份證的真偽,該機構顯然擁有更豐富的經驗和信息來確認身份證的真偽。上面介紹的兩種驗證模型,也是數字世界的兩種驗證模型,一種是需要CA或其指定機構參與的,一種是不需要CA參與的
- 對于不需要CA參與的證書應用模型,驗證用戶B應該具備CA證書(或證書鏈)、CRL這些基本的材料和驗證應用程序。對于需要CA參與的證書應用模型,用戶B幾乎可以不擁有任何資料,它只要可以理解CA提供的在線驗證協議就行了,現在通常使用的是OCSP協議。?
證書鏈
- 我們回頭看看圖,用戶A和用戶B的證書是不同CA簽發的,分別是CA1和CA2,那么如果A發給用戶B自己的證書并要求進行驗證,那么B應該怎么做呢?如果B沒有CA1的證書,那么B就沒有辦法確認用戶A證書中簽名的合法性,驗證過程顯然沒有辦法進行下去。同樣,要驗證CA1的證書,B也需要根CA的證書,以便提取其中的公鑰驗證其對CA1的簽名。所以,為了確保B能正確驗證自己的證書,A必須給B發送三個證書:自己的證書、CA1證書和根CA證書。這三個證書就構成了一個完整的證書鏈。
- ?一般來說,證書應用程序都應該支持證書鏈的構造和驗證,用戶只要將構造證書鏈需要的證書提供給應用程序就可以了。比如OpenSSL的指令verify,你只需要將構建一個完整證書鏈需要的證書都存放在一個文件(CAfile)或者一個目錄(CApath)中,并把這個相關的信息通過指令選項輸入,verify指令就會自動完成整個證書鏈的構造和驗證過程。
用戶的身份認證
- 上面我們已經順利通過一個證書的驗證了,實質上,我們僅僅是對證書本身的合法性和有效性進行了驗證,對于用戶是否確實擁有這個證書還需要進一步確認。需要再次強調的是,僅有證書是沒有多大意義的。千萬不要以為自己得到了管理員的一個數字證書就可以竊喜不已,事實上它毫無用處,在實際的應用協議中,在通過對你出示的證書進行驗證之后,還要驗證你是否確實擁有該證書。過程很簡單,提取證書中的公鑰,使用該公鑰加密一個隨機數,然后發送給你,并要求你解密后返回該隨機數。如果你確實是證書的主人,那么你擁有相應的私鑰,你可以解密發送過來的信息并得到隨機數,然后返回給對方證明你的身份,對方比較本地保存的隨機數和你返回的隨機數,如果一致,證明你能夠正確解密證書上公鑰加密的數據,確認你擁有證書相應的私鑰。而你如果是冒充的用戶,那么這時候你就束手無策了,你沒有辦法正確解密得到那個隨機數,從而也就狼狽地暴露了你的身份。
更多的問題
- 雖然我們有了一個合法的數字證書,但證書在具體應用環境或者協議中的使用要考慮的問題還可能有許多。首先面臨的就是證書格式問題,對于具體的應用程序來說,對證書的編碼格式可能有不同的限制和支持,比如一個使用非微軟本身密鑰產生器申請的證書需要在IE中使用,首先就必須將證書和密鑰封裝成PKCS#12格式才能導入到微軟的機制中,而OpenSSL則不存在這樣的限制。
- 其次可能還有證書本身的一些擴展字段問題,有些CA中心自己擴展了一些字段,但是這些字段在別的應用程序中并不一定能得到很好的支持,這樣有可能就會導致驗證失敗等問題,尤其是該擴展字段標記為關鍵擴展之后。這樣的問題要是啰嗦起來,數不勝數,如果想在碰到這些問題的時候能夠迅速解決,那么最主要的就是對整個密碼學技術和PKI應用有一個清晰的概念和認識。
CA的建立
- 建立一個投入實際應用的CA是一個非常復雜的問題,要考慮的不僅僅是技術上的問題,更多的是管理上的規范性問題。對于管理問題,不是本書關注的話題,不作更多的討論。這里要說的是,怎么從技術上建立一個CA服務器。前面我們介紹了證書的各個方面,都是假設CA已經存在,但是事實上,可能你并不能找到一個合適的CA,甚至,你的任務就是建立一個CA。這時候該做些什么?事實上你有很多選擇。微軟平臺自身就附帶了一個可選的CA服務器程序,該程序能夠實現申請證書和發放證書等功能。
- 此外,OpenCA也是一個選擇。你還可以選擇一個營利性的公共CA來建立你的證書服務體系。不過無論如何,在本書我們要討論的重點可能是OpenSSL提供的ca指令。我并非推薦大家使用OpenSSL的ca指令,但它確實有很多值得我們使用和研究的地方。首先它是開放源代碼的,這非常有好處,也適應國家對網絡安全產品的要求;其次它是免費獲得的,任何人都可以擁有,不存在太多的版權限制;再次,其功能也還不錯,通過幾次的改進,其功能已經遠遠超出了當時作為一個演示ca程序的范疇。無論你使用哪種CA應用程序,要使一個CA服務器開始運作,首先要為CA自身生成一對密鑰和一個證書。因為CA的證書安全性非常重要,所以其密鑰的長度應該比普通的證書密鑰長度長一些,比如采用2048位的RSA密鑰。如果CA是一個根CA,那么其證書就是一個自簽名證書,即使用自己的私鑰對證書內容(包括自己的公鑰)進行簽名。
- 如果不是一個根CA,那么應該向上級CA申請證書。OpenSSL的req指令可以提供生成證書請求和自簽名根證書的功能,在后面的章節中將會作詳細的介紹。CA擁有了自己的證書和私鑰之后,CA應用程序一般來說就可以開始運行了。