PKI体系详解_基于PKI体系的认证方式进行论述
<link rel="stylesheet" href="/css/blog-common.min.css?v=cGPZX-91MnVsFpGp_qDIwTwedO-J7MOgyTfTUau0qqk" />
<link id="MainCss" rel="stylesheet" href="/skins/anothereon001/bundle-anothereon001.min.css?v=9x2ZP2K8SSBJowZA6xv0D5FvOmlvd5g21u0NBEAEwfQ" />
<link type="text/css" rel="stylesheet" href="/css/hljs/cnblogs.css?v=2spjdq1Snjw5rAm9auWVRax8Gb7nftS4ORu-8fQ7JGM" />
<link id="mobile-style" media="only screen and (max-width: 767px)" type="text/css" rel="stylesheet" href="/skins/anothereon001/bundle-anothereon001-mobile.min.css?v=AikVcA3woZbE5dC36jgvTLxMtITzGppqPpum5r32N7g" />
<link type="application/rss+xml" rel="alternate" />
<link type="application/rsd+xml" rel="EditURI" />
<link type="application/wlwmanifest+xml" rel="wlwmanifest" />
<script>
var currentBlogId = 619746;
var currentBlogApp = 'precedeforetime';
var cb_enable_mathjax = false;
var isLogined = false;
var isBlogOwner = false;
var skinName = 'AnotherEon001';
var visitorUserId = '';
var hasCustomScript = false;
try {
if (hasCustomScript && document.referrer && document.referrer.indexOf('baidu.com') >= 0) {
Object.defineProperty(document, 'referrer', { value: '' });
Object.defineProperty(Document.prototype, 'referrer', { get: function(){ return ''; } });
}
} catch(error) { }
</script>
<script>
var currentPostDateAdded = '2020-07-28 02:04';
</script>
<script src="https://common.cnblogs.com/scripts/jquery-2.2.0.min.js"></script>
<script src="/js/blog-common.min.js?v=-1eTvcf83U0Xu5DR54ryFvO0O9pdTGGVJrDEDjIYF7Y"></script>
<script type="text/javascript">
window.codeHighlightEngine = 1
window.enableCodeLineNumber = false
</script>
<div id="wrapper">
precedeforetime
PKI(HTTPS)體系詳解
</h2>
<div class="postbody">
<div id="cnblogs_post_body" class="blogpost-body cnblogs-markdown">
PKI是什么
百度百科:
PKI是Public Key Infrastructure的首字母縮寫,翻譯過來就是公鑰基礎設施;PKI是一種遵循標準的利用公鑰加密技術為電子商務的開展提供一套安全基礎平臺的技術和規(guī)范。
X.509標準中,為了區(qū)別于權限管理基礎設施(Privilege Management Infrastructure,簡稱PMI),將PKI定義為支持公開密鑰管理并能支持認證、加密、完整性和可追究性服務的基礎設施]。這個概念與第一個概念相比,不僅僅敘述PKI能提供的安全服務,更強調PKI必須支持公開密鑰的管理。也就是說,僅僅使用公鑰技術還不能叫做PKI,還應該提供公開密鑰的管理。因為PMI僅僅使用公鑰技術但并不管理公開密鑰,所以,PMI就可以單獨進行描述了而不至于跟公鑰證書等概念混淆。X.509中從概念上分清PKI和PMI有利于標準的敘述。然而,由于PMI使用了公鑰技術,PMI的使用和建立必須先有PKI的密鑰管理支持。也就是說,PMI不得不把自己與PKI綁定在一起。當我們把兩者合二為一時,PMI+PKI就完全落在X.509標準定義的PKI范疇內。根據(jù)X.509的定義,PMI+PKI仍舊可以叫做PKI,而PMI完全可以看成PKI的一個部分。
PKI 既不是一個協(xié)議,也不是一個軟件,它是一個標準,在這個標準之下發(fā)展出的為了實現(xiàn)安全基礎服務目的的技術統(tǒng)稱為 PKI。
PKI的組成部分
百度百科:
PKI(Public Key Infrastructure)公鑰基礎設施是提供公鑰加密和數(shù)字簽名服務的系統(tǒng)或平臺,目的是為了管理密鑰和證書。一個機構通過采用PKI 框架管理密鑰和證書可以建立一個安全的網絡環(huán)境。PKI 主要包括四個部分:X.509 格式的證書(X.509 V3)和證書廢止列表CRL(X.509 V2);CA 操作協(xié)議;CA 管理協(xié)議;CA 政策制定。一個典型、完整、有效的PKI 應用系統(tǒng)至少應具有以下五個部分:
1) 認證中心CA CA 是PKI 的核心,CA負責管理PKI 結構下的所有用戶(包括各種應用程序)的證書,把用戶的公鑰和用戶的其他信息捆綁在一起,在網上驗證用戶的身份,CA 還要負責用戶證書的黑名單登記和黑名單發(fā)布,后面有CA 的詳細描述。
2) X.500 目錄服務器 X.500 目錄服務器用于發(fā)布用戶的證書和黑名單信息,用戶可通過標準的LDAP 協(xié)議查詢自己或其他人的證書和下載黑名單信息。
3) 具有高強度密碼算法(SSL) 的安全WWW服務器 Secure socket layer(SSL)協(xié)議最初由Netscape 企業(yè)發(fā)展,現(xiàn)已成為網絡用來鑒別網站和網頁瀏覽者身份,以及在瀏覽器使用者及網頁服務器之間進行加密通訊的全球化標準。
4) Web(安全通信平臺) Web 有Web Client 端和Web Server 端兩部分,分別安裝在客戶端和服務器端,通過具有高強度密碼算法的SSL協(xié)議保證客戶端和服務器端數(shù)據(jù)的機密性、完整性、身份驗證。
5) 自開發(fā)安全應用系統(tǒng) 自開發(fā)安全應用系統(tǒng)是指各行業(yè)自開發(fā)的各種具體應用系統(tǒng),例如銀行、證券的應用系統(tǒng)等。完整的PKI 包括認證政策的制定(包括遵循的技術標準、各CA 之間的上下級或同級關系、安全策略、安全程度、服務對象、管理原則和框架等)、認證規(guī)則、運作制度的制定、所涉及的各方法律關系內容以及技術的實現(xiàn)等。
作為WEB開發(fā)者其實只需要關注pki組成部分中的后三部分,高強度密碼算法SSL目前已經包含在https中,下面對https有專門的講解;web安全通信平臺可以理解為我們的瀏覽器和服務器,即可以建立https連接的兩個端點;自開發(fā)安全應用系統(tǒng)即是我們開發(fā)的支持pki驗證的系統(tǒng)。
HTTPS 詳解
HTTP VS HTTPS
使用HTTP有以下風險:
- 竊聽風險(eavesdropping): 通信使用明文(不加密),內容可能會被竊聽
- 篡改風險(tampering):不驗證通信方的身份,因此有可能遭遇偽裝
- 冒充風險(pretending):無法證明報文的完整性,所以有可能已遭篡改
當然,相對于HTTPS的安全性更高,HTTP也有自己的優(yōu)勢,即性能更好。
簡單來說,HTTPS比HTTP增加了SSL握手和對于傳輸數(shù)據(jù)加密解密的過程,握手部分的耗時差不多為建立TCP連接耗時的3倍到6倍(取決于數(shù)字證書的加密強度),另外對于傳輸數(shù)據(jù)的加密解密也會占用設備一部分的性能。
HTTPS/HTTP的區(qū)別和聯(lián)系
HTTPS = HTTP+SSL / TLS
對稱加密和非對稱加密
對稱加密
所謂的“對稱加密技術”,意思就是說:“加密”和“解密”使用相同的密鑰。就好比用 7zip 或 WinRAR 創(chuàng)建一個帶密碼(口令)的加密壓縮包。當你下次要把這個壓縮文件解開的時候,你需要輸入同樣的密碼。在這個例子中,密 碼/口令就如同剛才說的“密鑰”。
缺陷:對稱加密的密鑰如何傳輸,第一次傳輸?shù)臅r候肯定是明文,那么對稱密鑰還是會存在被竊取的風險,以及客戶端如何確認服務端的身份。
對稱加密經典算法:AES,DES,3DES,TDEA,Blow?sh,RC5,IDEA。
非對稱加密
百度百科
非對稱加密算法需要兩個密鑰:公開密鑰(public key)和私有密鑰(private key)。
公開密鑰與私有密鑰是一對,如果用公開密鑰對數(shù)據(jù)進行加密,只有用對應的私有密鑰才能解密;如果用私有密鑰對數(shù)據(jù)進行加密,那么只有用對應的公開密鑰才能解密。因為加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。
非對稱加密算法實現(xiàn)機密信息交換的基本過程是:甲方生成一對密鑰并將其中的一把作為公用密鑰向其 它方公開;得到該公用密鑰的乙方使用該密鑰對機密信息進行加密后再發(fā)送給甲方;甲方再用自己保存的另 一把專用密鑰對加密后的信息進行解密。另一方面,甲方可以使用乙方的公鑰對機密信息進行簽名后再發(fā)送 給乙方;甲方再用自己的私匙對乙方發(fā)送回來的數(shù)據(jù)進行驗簽。
非對稱加密經典算法:RSA、Elgamal、背包算法、Rabin、D-H、ECC(橢圓曲線加密算法)。
缺陷:非對稱加密可以解決對稱加密被竊取的問題,但依然無法驗證服務器的身份信息。
非對稱加密被劫持情況
對稱加密和非對稱加密算法效率對比
對稱加密(AES):
-
AES加密的時間與被加密文件的大小正線性增長,加密1G的文件大概需要4分多鐘,加密速度較快。
-
加密后的文件大小是原始文件大小的兩倍。
-
解密文件所需時間是加密時間的兩倍(這個應該是加密文件是原始文件大小兩倍造成的)。
非對稱加密(RSA):
-
RSA加密算法加密時間很短,基本可以忽略不計。但是,在解密時,RSA顯的比較慢,解密時間與解密文件 的大小呈現(xiàn)線性增長趨勢。加密1M的文件大概需要5秒,但是解密卻需要4分鐘。
-
加密后的文件與原始文件的大小基本相同。
-
解密的效率遠低于加密效率,按照這個時間去計算,加密1G的文件需要1分鐘,但是解密卻需要65小時。
AES和RSA加密算法效率對比
CA 認證
無論是對稱加密還是非對稱加密,都遺留了一個問題沒有解決,那就是如何證明我們訪問的網站就是我們要訪問的網站,而不是他人偽造的,即中間人攻擊和信息抵賴的問題,這里就用到了CA證書。
百度百科
CA認證,即電子認證服務 ,是指為電子簽名相關各方提供真實性、可靠性驗證的活動。
證書頒發(fā)機構(CA, Certi?cate Authority)即頒發(fā)數(shù)字證書的機構。是負責發(fā)放和管理數(shù)字證書的權威機構,并作為電子商務交易中受信任的第三方,承擔公鑰體系中公鑰的合法性檢驗的責任。
CA中心為每個使用公開密鑰的用戶發(fā)放一個數(shù)字證書,數(shù)字證書的作用是證明證書中列出的用戶合法擁 有證書中列出的公開密鑰。CA機構的數(shù)字簽名使得攻擊者不能偽造和篡改證書。在SET交易中,CA不僅對持 卡人、商戶發(fā)放證書,還要對獲款的銀行、網關發(fā)放證書。
CA是證書的簽發(fā)機構,它是PKI的核心。CA是負責簽發(fā)證書、認證證書、管理已頒發(fā)證書的機關。它要制 定政策和具體步驟來驗證、識別用戶身份,并對用戶證書進行簽名,以確保證書持有者的身份和公鑰的擁有 權。
CA 也擁有一個證書(內含公鑰)和私鑰。網上的公眾用戶通過驗證 CA 的簽字從而信任 CA ,任何人都可以得到 CA的證書(含公鑰),用以驗證它所簽發(fā)的證書。
如果用戶想得到一份屬于自己的證書,他應先向 CA 提出申請。在 CA 判明申請者的身份后,便為他分配一個公鑰,并且 CA 將該公鑰與申請者的身份信息綁在一起,并為之簽字后,便形成證書發(fā)給申請者。
如果一個用戶想鑒別另一個證書的真?zhèn)危陀?CA 的公鑰對那個證書上的簽字進行驗證,一旦驗證通過,該證書就被認為是有效的。
為保證用戶之間在網上傳遞信息的安全性、真實性、可靠性、完整性和不可抵賴性,不僅需要對用戶的 身份真實性進行驗證,也需要有一個具有權威性、公正性、唯一性的機構,負責向電子商務的各個主體頒發(fā) 并管理符合國內、國際安全電子交易協(xié)議標準的電子商務安全證,并負責管理所有參與網上交易的個體所需 的數(shù)字證書,因此是安全電子交易的核心環(huán)節(jié)。
解決上述身份驗證問題的關鍵是確保獲取的公鑰途徑是合法的,能夠驗證服務器的身份信息,為此需要引入權威的第三方機構CA(如沃通CA)。CA 負責核實公鑰的擁有者的信息,并頒發(fā)認證”證書”,同時能夠為使用者提供證書驗證服務,即PKI體系(PKI基礎知識)。
基本的原理為,CA負責審核信息,然后對關鍵信息利用私鑰進行”簽名”,公開對應的公鑰,客戶端可以利用公鑰驗證簽名。CA也可以吊銷已經簽發(fā)的證書,基本的方式包括兩類 CRL 文件和 OCSP。CA使用具體的流程如下:
1. 服務方S向第三方機構CA提交公鑰、組織信息、個人信息(域名)等信息并申請認證;
-
CA通過線上、線下等多種手段驗證申請者提供信息的真實性,如組織是否存在、企業(yè)是否合法,是否擁有域名的所有權等;
-
如信息審核通過,CA會向申請者簽發(fā)認證文件-證書。
證書包含以下信息:申請者公鑰、申請者的組織信息和個人信息、簽發(fā)機構CA的信息、有效時間、證書序列號等信息的明文,同時包含一個簽名;
簽名的產生算法:首先,使用散列函數(shù)計算公開的明文信息的信息摘要,然后,采用CA的私鑰對信息摘要進行加密,密文即簽名;
-
客戶端 C 向服務器 S 發(fā)出請求時,S 返回證書文件;
-
客戶端 C 讀取證書中的相關的明文信息,采用相同的散列函數(shù)計算得到信息摘要,然后,利用對應CA的公鑰解密簽名數(shù)據(jù),對比證書的信息摘要,如果一致,則可以確認證書的合法性,即公鑰合法;
-
客戶端然后驗證證書相關的域名信息、有效時間等信息;
-
客戶端會內置信任CA的證書信息(包含公鑰),如果CA不被信任,則找不到對應 CA的證書,證書也會被判定非法。
-
在這個過程注意幾點:
a.申請證書不需要提供私鑰,確保私鑰永遠只能服務器掌握;
b.證書的合法性仍然依賴于非對稱加密算法,證書主要是增加了服務器信息以及簽名;
c.內置 CA 對應的證書稱為根證書,頒發(fā)者和使用者相同,自己為自己簽名,即自簽名證書(為什么說”部署自簽SSL證書非常不安全”)
d.證書=公鑰+申請者與頒發(fā)者信息+簽名;
即便有人截取服務器證書,再發(fā)給客戶端,想冒充服務器,也無法實現(xiàn)。因為證書和url的域名是綁定的。
免費獲取CA證書的幾種方式
- 從相關商業(yè)機構申請,以阿里云為例:
- 使用證書工具生成(Keytool或者Openssl): 詳見實操部分
SSL/TLS的聯(lián)系與區(qū)別
SSL/TLS的背景
1994年,NetScape 公司設計了 SSL 協(xié)議的1.0版,但是未發(fā)布。
1995年,NetScape 公司發(fā)布 SSL 2.0版,很快發(fā)現(xiàn)有嚴重漏洞。
1996年,SSL 3.0 版問世,得到大規(guī)模應用。
1999年,互聯(lián)網標準化組織 ISOC 接替 NetScape 公司,發(fā)布了 SSL 的升級版 TLS 1.0 版。
2006年和2008年,TLS 進行了兩次升級,分別為 TLS 1.1 版和 TLS 1.2 版。最新的變動是2011年 TLS 1.2的修訂版。
對于二者的關系,可以說是同一事物在不同時期的表現(xiàn)。TLS 1.0通常被標示為SSL 3.1,TLS 1.1為SSL 3.2,TLS 1.2 為SSL 3.3。
SSL(Secure Socket Layer,安全套接字層)
SSL協(xié)議位于TCP/IP協(xié)議與各種應用層協(xié)議之間,為數(shù)據(jù)通訊提供安全支持。SSL協(xié)議可分為兩層,SSL記錄協(xié)議層(SSL Record Protocol):它建立在可靠的傳輸協(xié)議(如TCP)之上,為高層協(xié)議提供數(shù)據(jù)封裝、壓縮、加密等基本功能的支持。SSL握手協(xié)議層(SSL Handshake Protocol):它建立在SSL記錄協(xié)議之上,用于在實際的數(shù)據(jù)傳輸開始前,通訊雙方進行身份認證、協(xié)商加密算 法、交換加密密鑰等。
SSL協(xié)議提供的服務主要有:
? 1)認證用戶和服務器,確保數(shù)據(jù)發(fā)送到正確的客戶機和服務器;
2)加密數(shù)據(jù)以防止數(shù)據(jù)中途被竊取;
3)維護數(shù)據(jù)的完整性,確保數(shù)據(jù)在傳輸過程中不被改變。
SSL協(xié)議的握手流程:
以上工作流程分為五步:
第一步,愛麗絲給出協(xié)議版本號、一個客戶端生成的隨機數(shù)1(Client random),以及客戶端支持的加密方法。
第二步,鮑勃確認雙方使用的加密方法,并給出數(shù)字證書、以及一個服務器生成的隨機數(shù)2(Server random)。
第三步,愛麗絲確認數(shù)字證書有效,然后生成一個新的隨機數(shù)3(Premaster secret),并使用數(shù)字證書中的公鑰,
加密這個隨機數(shù),發(fā)給鮑勃。同時依據(jù)三個隨機數(shù)根據(jù)指定算法生成對稱密鑰。另如果開啟了雙向認證,那么在這一步客戶端會將自己的證書的發(fā)送給服務器。
第四步,鮑勃使用自己的私鑰,獲取愛麗絲發(fā)來的隨機數(shù)(即Premaster secret)。服務器開始根據(jù)約定的加密方
法,使用前面的三個隨機數(shù),生成”對話密鑰”(session key),用來加密接下來的整個對話過程。
第五步,愛麗絲和鮑勃用對話密鑰將對話加密后開始傳輸。
TLS(Transport Layer Security Protocol,傳輸層安全協(xié)議)
是IETE(工程任務組)指定的一種新的協(xié)議,它建立在SSL 3.0協(xié)議規(guī)范之上,是SSL 3.0的后續(xù)版本,也用于在兩個通信應用程序之間提供保密性和數(shù)據(jù)完整性。
該協(xié)議也由兩部分組成:TLS記錄協(xié)議(TLS Record)和TLS握手協(xié)議(TLS Handshake)。
TLS與SSL的差異:
1)版本號:TLS記錄格式與SSL記錄格式相同,但版本號的值不同,TLS的版本1.0使用的版本號為SSLv3.1。
2)報文鑒別碼:SSLv3.0和TLS的MAC算法及MAC計算的范圍不同。TLS使用RFC-2104定義的HMAC算 法。SSLv3.0使用了相似的算法,兩者差別在于SSLv3.0中,填充字節(jié)與密鑰之間采用的是連接運算,而HMAC算法 采用的異或運算。但是兩者的安全程度是相同的。
3)偽隨機函數(shù):TLS使用了稱為PRF的偽隨機函數(shù)來將密鑰擴展成數(shù)據(jù)塊,是更安全的方式。
4)報警代碼:TLS支持幾乎所有的SSLv3.0報警代碼,而且TLS還補充定義了很多報警代碼,如解密失敗(decryption_failed)、記錄溢出(record_over?ow)、未知CA(unknown_ca)、拒絕訪問(access_denied)等。
5)密文族和客戶證書:SSLv3.0和TLS存在少量差別,即TLS不支持Fortezza密鑰交換、加密算法和客戶證書。
6)certi?cate_verify和?nished消息:SSLv3.0和TLS在用certi?cate_verify和?nished消息計算MD5和SHA-1散列碼時,計算的輸入有少許差別,但安全性相當。
7)加密計算:TLS和SSLv3.0在計算主密值(master secret)時采用的方式不同。
8)填充:用戶數(shù)據(jù)加密之前需要增加的填充字節(jié)。在SSL中,填充后的數(shù)據(jù)長度喲啊達到密文快長度的最 小整數(shù)倍。而在TLS中,填充后的數(shù)據(jù)長度可以是密文塊長度的任意整數(shù)倍(但填充的最大長度為255字節(jié)),這 種方式可以防止基于對報文長度進行分析的攻擊。
TLS的主要增強內容:
TLS的主要目標是使SSL更安全,并使協(xié)議的規(guī)范更精確和完善。TLS在SSL v3.0的基礎上,提供了以下增加內容:
1)更安全的MAC算法
2)更嚴密的警報
3)“灰色區(qū)域”規(guī)范的更明確的定義
TLS對于安全性的改進:
1)對于消息認證使用密鑰散列法:TLS使用“消息認證代碼的密鑰散列法”(HMAC),當記錄在開放的網絡(如因特網)上傳送時,該代碼確保記錄不會被變更。SSLv3.0還提供鍵控消息認證,但HMAC比SSLv3.0使用(消息認證代碼)MAC功能更安全。
2)增強的偽隨機功能(PRF):PRF生成密鑰數(shù)據(jù)。在TLS中,HMAC定義PRF。PRF使用兩種散列算法保 證其安全性。如果任一算法暴露了,只要第二種算法未暴露,則數(shù)據(jù)仍然是安全的。
3)改進的已完成消息驗證:TLS和SSLv3.0都對兩個端點提供已完成的消息,該消息認證交換的消息沒有 被變更。然而,TLS將此已完成消息基于PRF和HMAC值之上,這也比SSLv3.0更安全。
4)一致證書處理:與SSLv3.0不同,TLS試圖指定必須在TLS之間實現(xiàn)交換的證書類型。
5)特定警報消息:TLS提供更多的特定和附加警報,以指示任一會話端點檢測到的問題。TLS還對何時應 該發(fā)送某些警報進行記錄。
綜上所述,SSL和TLS 沒有本質區(qū)別,二者的工作流程基本一致,只是TLS在SSL的基礎上對于安全性做了一些增強。
雙向認證和單向認證
單向認證是指客戶端根據(jù)服務器傳過來的證書信息校驗服務器的合法性,上文的SSL握手流程就是單向認證。
服務器的合法性包括:
1.證書是否過期。
2.發(fā)行服務器證書的CA是否可靠。
3.發(fā)行者證書的公鑰能否正確解開服務器證書的"發(fā)行者的數(shù)字簽名"。
4.服務器證書上的域名是否和服務器的實際域名相匹配。
如果合法性驗證沒有通過,則瀏覽器會給用戶一個警告提示訪問網站不安全,讓用戶選擇是繼續(xù)訪問還是終止訪問。
服務器合法性通過,以淘寶為例:
服務器合法性校驗不通過,原因是這個證書是自己簽發(fā),CA不受信:
雙向認證是在單向認證的基礎上,增加了一步服務器校驗客戶端證書的動作,這一步驟存在于SSL握手流程的第三步。一般在對用戶身份信息比較敏感的網站上會使用,比如銀行系統(tǒng)的U盾,以及此次龍灣項目的PKI登陸。如果服務器校驗客戶端證書成功,則正常訪問,如果失敗,瀏覽器則會直接提示無法訪問該網站。
服務器獲取客戶端證書:
服務器校驗客戶端證書失敗(服務器開啟了強制校驗,沒有證書或者證書不符合):
服務器證書和客戶端證書的區(qū)別與聯(lián)系
服務器證書和客戶端證書沒有本質區(qū)別,都是一個包含公鑰和私鑰的文件。但是并不建議二者交換使用,在上文的單向認證中的服務器合法性中會校驗服務器證書上的域名和服務器的實際域名是否相匹配,而這個域名信息是服務器證書里面獨有的,客戶端證書中獨有的信息是則是用戶身份信息,如果二者交換使用,瀏覽器會提示服務器證書域名不匹配,那么該服務器證書則會不受信,也就失去了使用服務器證書的意義。
服務器證書和客戶端證書如何建立信任關系
在了解這個問題過程中我曾經進入一個誤區(qū),以為服務器校驗客戶端證書是依賴于將每一個客戶端證書的公鑰導入服務器證書的證書庫(即服務器證書文件)中。
而實際上服務器校驗客戶端證書是否合法是取決于服務器證書是否信任客戶端證書的證書鏈。也可以理解為服務器證書信任頒發(fā)客戶端證書的CA。在操作層面這個建立這個信任關系也是將簽發(fā)客戶端證書的CA的公鑰導入服務器證書,但從原理層面來說,相較于上面的誤區(qū),信任證書鏈的話只需要導入一次CA的公鑰即可,而不用單獨將每個客戶端證書的公鑰導入服務器證書。
我在開發(fā)過程中,甲方只給我一個服務器證書,并沒有給客戶端證書,為了模擬測試只能自己簽發(fā)客戶端證書,但自己簽發(fā)的證書沒有CA信息通過校驗證書鏈肯定是不行的,這時候只能使用上面的導入客戶端公鑰的辦法了,即先將自己生成的客戶端證書中的公鑰導出,然后將該公鑰導入服務器證書中使服務器證書信任該公鑰,這一點可以看后面的操作部分。
另外還有一點就是校驗客戶端證書時并沒有做業(yè)務層面的判斷,假如某CA簽發(fā)了N個客戶端證書,而服務器證書又信任這個CA的證書鏈,那么對于服務器證書來說,這些客戶端證書是沒有任何區(qū)別(因為都是受信的),如果想建立證書與用戶之間的關系,還需要在代碼層面來操作。
關于服務器證書和客戶端證書建立信任關系的討論
證書鏈
百度百科:
證書鏈(certificate chain)
證書鏈可以有任意環(huán)節(jié)的長度,所以在三節(jié)的鏈中,信任錨證書CA 環(huán)節(jié)可以對中間證書簽名;中間證書的所有者可以用自己的私鑰對另一個證書簽名。CertPath API 可以用來遍歷證書鏈以驗證有效性,也可以用來構造這些信任鏈。
Web 瀏覽器已預先配置了一組瀏覽器自動信任的根 CA 證書。來自其他證書授權機構的所有證書都必須附帶證書鏈,以檢驗這些證書的有效性。證書鏈是由一系列 CA 證書發(fā)出的證書序列,最終以根 CA 證書結束。
證書最初生成時是一個自簽名證書。自簽名證書是其簽發(fā)者(簽名者)與主題(其公共密鑰由該證書進行驗證的實體)相同的證書。如果擁有者向 CA 發(fā)送證書簽名請求 (CSR),然后輸入響應,自簽名證書將被證書鏈替換。鏈的底部是由 CA 發(fā)布的、用于驗證主題的公共密鑰的證書(回復)。鏈中的下一個證書是驗證 CA 的公共密鑰的證書。通常,這是一個自簽名證書(即,來自 CA、用于驗證其自身的公共密鑰的證書)并且是鏈中的最后一個證書。
在其他情況下,CA 可能會返回一個證書鏈。在此情況下,鏈的底部證書是相同的(由 CA 簽發(fā)的證書,用于驗證密鑰條目的公共密鑰),但是鏈中的第二個證書是由其他 CA 簽發(fā)的證書,用于驗證您向其發(fā)送了 CSR 的 CA 的公共密鑰。然后,鏈中的下一個證書是用于驗證第二個 CA 的密鑰的證書,依此類推,直至到達自簽名的根證書。因此,鏈中的每個證書(第一個證書之后的證書)都需要驗證鏈中前一個證書的簽名者的公共密鑰。
Windows系統(tǒng)中的證書鏈:
服務器證書、中間證書與根證書在一起組合成一條合法的證書鏈,證書鏈的驗證是自下而上的信任傳遞的過程。
? 二級證書結構存在的優(yōu)勢:
a.減少根證書結構的管理工作量,可以更高效的進行證書的審核與簽發(fā);
b.根證書一般內置在客戶端中,私鑰一般離線存儲,一旦私鑰泄露,則吊銷過程非常困難,無法及時補救;
c.中間證書結構的私鑰泄露,則可以快速在線吊銷,并重新為用戶簽發(fā)新的證書;
d.證書鏈四級以內一般不會對 HTTPS 的性能造成明顯影響。
證書鏈有以下特點:
a.同一本服務器證書可能存在多條合法的證書鏈。因為證書的生成和驗證基礎是公鑰和私鑰對,如果采用相同的公鑰和私鑰生成不同的中間證書,針對被簽發(fā)者而言,該簽發(fā)機構都是合法的 CA,不同的是中間證書的簽發(fā)機構不同;
b.不同證書鏈的層級不一定相同,可能二級、三級或四級證書鏈。中間證書的簽發(fā)機構可能是根證書機構也可能是另一個中間證書機構,所以證書鏈層級不一定相同。
證書格式
根據(jù)不同的服務器以及服務器的版本,我們需要用到不同的證書格式,就市面上主流的服務器來說,大概有以下格式:
-
DER/CER,文件是二進制格式,只保存證書,不保存私鑰。
-
CRT,可以是二進制格式,可以是文本格式,與DER格式相同,不保存私鑰。
-
PEM,一般是文本格式,可保存證書,可保存私鑰。
-
PFX/P12,二進制格式,同時包含證書和私鑰,一般有密碼保護。
-
JKS,二進制格式,同時包含證書和私鑰,一般有密碼保護。
DER
該格式是二進制文件內容,Java 和 Windows 服務器偏向于使用這種編碼格式。
OpenSSL 查看:
openssl x509 -in certificate.der -inform der -text -noout
轉換為 PEM:
openssl x509 -in cert.crt -inform der -outform pem -out cert.pem
PEM
Privacy Enhanced Mail,一般為文本格式,以 -----BEGIN----- 開頭,以-----END----- 結尾。中間的內容是BASE64 編碼。這種格式可以保存證書和私鑰,有時我們也把PEM 格式的私鑰的后綴改為 .key 以區(qū)別證書與私鑰。具體你可以看文件的內容。這種格式常用于 Apache和 Nginx服務器。
OpenSSL 查看:
openssl x509 -in certificate.pem -text -noout
轉換為 DER:
openssl x509 -in cert.crt -outform der -out cert.der
CRT
Certi?cate 的簡稱,有可能是 PEM 編碼格式,也有可能是 DER 編碼格式。如何查看請參考前兩種格式。
PFX/P12
Predecessor of PKCS#12,這種格式是二進制格式,且證書和私鑰存在一個 PFX 文件中。一般用于 Windows上的 IIS 服務器,window上可以直接安裝。改格式的文件一般會有一個密碼用于保證私鑰的安全。
OpenSSL 查看:
openssl pkcs12 -in for-iis.pfx
轉換為 PEM:
openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes
JKS/KEYSOTRE/TRUSTSTORE
Java Key Storage,這是 JAVA的專屬格式,利用 JAVA 的一個叫 keytool 的 工具可以進行格式轉換。一般用于 Tomcat 服務器。
實操部分
生成證書
自己簽發(fā)證書可以通過JDK自帶的工具Keytool或者Linux上的openssl來進行,二者都很容易百度到相關資料,本文只對keytool方式進行簡單講解。
生成服務器證書
keytool -genkey -v -alias tomcat -keyalg RSA -keystore
F:\baidu\keystore\tomcat.keystore -validity 36500
-alias 證書別名,可選,任意,但建議取有意義的值
-keyalg 生成證書所使用的算法
-keystore 生成的證書文件保存位置
-validity 證書有效期,36500表示100年,默認值是90天
注意:
-
名字與姓氏即為服務器的域名或者ip,如果是合法機構簽發(fā)的證書,域名或者ip匹配不上會提示不受信,雖然我們自己簽發(fā)的證書本來就是不受信的,但還是建議這里填有意義的域名或者ip。
-
密鑰庫口令需要記住,無論是配置https還是向密鑰庫中添加信任的公鑰時都會用到。
生成客戶端證書
keytool -genkey -v -alias mykey -keyalg RSA -storetype PKCS12 -keystore
F:\baidu\keystore\client.key.p12
生成證書后在windows系統(tǒng)中可以直接雙擊文件進行安裝。
讓服務器信任客戶端證書
將客戶端證書導出為一個單獨的CER文件。
keytool -export -alias mykey -keystore F:\baidu\keystore\client.key.p12 -storetype
PKCS12 -storepass password -rfc -file F:\baidu\keystore\client.key.cer
注:password為客戶端證書的密碼,即第一步生成服務器證書時的密鑰庫口令。
將CER文件導入到服務器的證書庫。
讓客戶端信任服務器證書
把服務器證書導出為CER文件,在windows中可以直接雙擊安裝.cer文件。
keytool -keystore F:\baidu\keystore\\tomcat.keystore -export -alias tomcat -file
F:\baidu\keystore\tomcat.cer
Windows 系統(tǒng)中查看已安裝的證書
Win+R 打開運行窗口,輸入certmgr.msc
如果上文中生成的客戶端證書(文件擴展名為.p12)成功安裝,那么在個人證書可以看到,如果沒有,則可能默認證書沒有安裝到個人證書文件夾下,可以重新安裝一遍并在證書安裝位置時手動將其修改為”個人”,如下是我的系統(tǒng)中安裝的證書:
對于自己簽發(fā)的證書,頒發(fā)給和頒發(fā)者都是相同的(這兩個值就是生成客戶端證書時填入的名字和姓氏),而對于CA簽發(fā)的則是不同的,下圖中的第一個證書是我在阿里云上申請的免費的證書,可以看到頒發(fā)者是商業(yè)機構。
對于這些證書可以通過右鍵來導出公鑰或者私鑰(如果有并且允許導出),導出私鑰時會提示輸入密鑰庫的密碼。
單機 TOMCAT 配置HTTPS
修改 server.xml 配置文件
在server.xml中增加
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="D:\services\apache-tomcat-8.5.34\cert18145_www.showsouth.top_tomcat18145_www.showsouth.top.pfx"
keystoreType="PKCS12"
keystorePass="xxxxxx" URIEncoding="UTF-8"/>
| 屬性 | 描述 |
|---|---|
| clientAuth | 如果設為true,表示Tomcat要求所有的SSL客戶出示安全證書,對SSL客戶進行身份驗證 |
| keystoreFile | 指定keystore文件的存放位置,可以指定絕對路徑,也可以指定相對于<CATALINA_HOME>(Tomcat安裝目錄)環(huán)境變量 的相對路徑。如果此項沒有設定,默認情況下,Tomcat將從當前操作系統(tǒng)用戶的用戶目錄下讀取名為“.keystore”的文件。 |
| keystorePass | 指定keystore的密碼,如果此項沒有設定,在默認情況下,Tomcat將使用“changeit”作為默認密碼。 |
| sslProtocol | 指定套接字(Socket)使用的加密/解密協(xié)議,默認值為TLS,用戶不應該修改這個默認值。 |
| ciphers | 指定套接字可用的用于加密的密碼清單,多個密碼間以逗號(,)分隔。如果此項沒有設定,在默認情況下,套接字可以使用任意一個可用的密碼。 |
啟動tomcat,訪問對應的url:
另因為我的這個阿里云申請的證書是授權給www.showsouth.top的這個域名,然后為了校驗通過,修改本機hosts文件,將www.showsouth.top映射到127.0.0.1。
分以下幾種情況訪問:
1.域名和證書內域名匹配:
訪問https://www.showsouth.top:8443 , 如下,可以看到瀏覽器提示安全(firefox的提示更加友好),如果是自己生成的證書,即便二者匹配,瀏覽器也會提示不安全。
2.域名和證書內域名不匹配:
訪問https://127.0.0.1:8443,firefox會提示服務器域名與證書中的域名不匹配的警告信息(這個提示信息只有Firefox有,chrome沒有,只會提示網站不安全),讓用戶選擇是否繼續(xù)訪問。
通過以上兩種訪問方式,即可以驗證上文提到的服務器合法性的第四條。
繼續(xù)選擇訪問之后會地址欄會提示不安全,如下:
3:以HTTP訪問(可選):
開啟HTTPS后,對于HTTP請求有以下三種處理方式:
? a.僅以https訪問,關閉http;
? b.https/http同時都可以訪問;
? c.http端口依然開放,但將所有的http請求重定向至https。
POSTMAN 訪問HTTPS請求
單向認證
postman訪問的接口如果是單向認證并且證書可以成功校驗通過,則https或者http對于用戶來說沒有區(qū)別,但如果使用了https并且服務器證書不受信,則postman會直接報錯,如下,這種情況可以通過在設置種關閉ssl證書校驗解決。
雙向認證
postman配置雙向認證比較麻煩,需要將客戶端證書分離成公鑰和私鑰,格式貌似只支持pem格式,然后再設置的證書選項中配置即可。
Spring Boot 配置HTTPS
springboot配置https講三種方式,第一種是springboot原生的配置文件配置,第二種和第三種都是通過代碼配置,但分別針對tomcat容器和jetty容器。第一種和第二種springboot官方文檔都有詳細講解,下面會直接引用官方文檔內容,jetty容器的會單獨貼代碼。
通過Spring Boot 配置文件配置HTTPS
spring boot官方文檔 配置https
核心配置:
server.port=8443
server.ssl.key-store=classpath:tomcat.keystore
server.ssl.key-store-password=123456
server.ssl.keyStoreType=PKCS12
server.ssl.client-auth=want (僅雙向認證時需要)
可選配置(意思就是我也不是很懂):
server.ssl.trust-store=classpath:tomcat.keystore
server.ssl.trust-store-password=123456
server.ssl.protocol=
server.ssl.enabled=false
server.ssl.key-password=
server.ssl.ciphers=
server.ssl.enabled-protocols=
server.ssl.trust-store-provider=
server.ssl.key-alias=
server.ssl.key-store-provider=
server.ssl.key-store-type=
server.ssl.trust-store-type=
核心配置的各參數(shù)含義可以參考單機tomcat配置中的各參數(shù)含義理解。
主要講下核心配置中的server.ssl.client-auth=want,這個參數(shù)有在雙向認證時需要配置,其有兩個值need和want(后文中的needClientAuth/wantClientAuth 含義與這兩個值相同)。下面分別講解:
need:開啟雙向認證,強制驗證客戶端證書。如果用戶沒有證書或者拒絕提供用戶證書(瀏覽器層面的操作),則SSL連接會直接斷開,瀏覽器顯示效果與服務器校驗客戶端證書失敗(服務器開啟了強制校驗,沒有證書或者證書不符合)的第二張圖相同,必須在用戶提供證書的前提下才能和服務器建立SSL連接。
want:開啟雙向認證,但校驗客戶端證書的操作是可選的,如果用戶沒有證書或拒絕提供證書,SSL連接依然進行,但在服務器端讀到的客戶端證書為空。
使用配置文件配置HTTPS的優(yōu)點是簡單,并且不用對代碼進行改動。缺點是通過配置文件配置對于HTTP/HTTPS僅能二選一,如果需要同時開啟HTTP和HTTPS,則必須要通過代碼層面配置。
Using configuration such as the preceding example means the application no longer supports a plain HTTP connector at port 8080. Spring Boot does not support the configuration of both an HTTP connector and an HTTPS connector through
application.properties. If you want to have both, you need to configure one of them programmatically. We recommend usingapplication.propertiesto configure HTTPS, as the HTTP connector is the easier of the two to configure programmatically. See thespring-boot-sample-tomcat-multi-connectorssample project for an example.
Spring boot tomcat 容器代碼配置同時支持HTTP和HTTPS
在配置文件中配置https,同上,然后在代碼中添加支持http的配置。
代碼如下:
/** * 配置一個TomcatEmbeddedServletContainerFactory bean * * @return */ @Bean public EmbeddedServletContainerFactory servletContainer() {TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() { @Override protected void postProcessContext(Context context) { SecurityConstraint securityConstraint = new SecurityConstraint(); securityConstraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection = new SecurityCollection(); collection.addPattern("/*"); securityConstraint.addCollection(collection); context.addConstraint(securityConstraint); } }; tomcat.addAdditionalTomcatConnectors(initiateHttpConnector()); return tomcat; } /** * 讓我們的應用支持HTTP是個好想法,但是需要重定向到HTTPS, * 但是不能同時在application.properties中同時配置兩個connector, * 所以要以編程的方式配置HTTP connector,然后重定向到HTTPS connector * * @return Connector */ private Connector initiateHttpConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); // http端口 connector.setPort(8080); connector.setSecure(false); // https端口 connector.setRedirectPort(7443); return connector; }}
結合單機tomcat配置https的配置文件,可以看到配置HTTP或者HTTPS連接的核心都是Connector,下面的jetty容器配置的核心也是添加多個Connector。
Spring Boot Jetty 容器同時配置HTTP和HTTPS
使用jetty配置時就沒有結合配置文件使用了,而是直接在Spring Boot啟動類中添加兩個Connector,分別支持HTTP和HTTPS。
代碼如下:
@Bean public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory( JettyServerCustomizer jettyServerCustomizer) { JettyEmbeddedServletContainerFactory factory = new JettyEmbeddedServletContainerFactory(); factory.addServerCustomizers(jettyServerCustomizer); return factory; }@Bean
public JettyServerCustomizer jettyServerCustomizer() {return server -> {
// Tweak the connection config used by Jetty to handle incoming HTTP
// connections
final QueuedThreadPool threadPool = server.getBean(QueuedThreadPool.class);
threadPool.setMaxThreads(500);
threadPool.setMinThreads(50);List<Connector> connectors = new ArrayList<>(); //創(chuàng)建HTTP Connector ServerConnector connector = new ServerConnector(server); //HTTP port connector.setPort(ServerSetting.getPort()); connectors.add(connector); if (ServerSetting.getApiType().equals(ApiTypeEnum.SERVICE.getValue()) && ServerSetting.getPkiServerRun()) { // 創(chuàng)建HTTPS Connector,以下各參數(shù)和單機tomcat中各參數(shù)含義相同 SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(ServerSetting.getKeystoreFilePath()); sslContextFactory.setKeyStorePassword(ServerSetting.getKeystorePassword()); sslContextFactory.setWantClientAuth(ServerSetting.getWantClientAuth()); HttpConfiguration config = new HttpConfiguration(); config.setSecureScheme(HttpScheme.HTTPS.asString()); config.addCustomizer(new SecureRequestCustomizer()); ServerConnector sslConnector = new ServerConnector( server, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), new HttpConnectionFactory(config)); // HTTPS port sslConnector.setPort(ServerSetting.getHttpsPort()); connectors.add(sslConnector); } server.setConnectors(connectors.toArray(new Connector[]{})); }; }最后說一個小問題,Spring Boot啟動時會先讀取 application.properties中的端口
server.port及協(xié)議配置,如果沒有,則默認以HTTP 8080端口啟動,這意味著上面的Jetty容器的配置方式在啟動時日志會提示以8080端口初始化,日志如下:2019-01-04 12:14:37 CST INFO [main] org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory.getEmbeddedServletContainer(JettyEmbeddedServletContainerFactory.java:149) - Server initialized with port: 8080這個是正常的,但如果在代碼中進行的相應的端口配置,則會自動覆蓋上面的初始化配置。
從如下日志中可以看到代碼中設置的端口及協(xié)議重新初始化:
2019-01-04 11:42:16 CST INFO [main] org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:266) - Started ServerConnector@5ab0260{HTTP/1.1}{0.0.0.0:8083} 2019-01-04 11:42:16 CST INFO [main] org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:266) - Started ServerConnector@6603902b{SSL-HTTP/1.1}{0.0.0.0:8443} 2019-01-04 11:42:16 CST INFO [main] org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainer.start(JettyEmbeddedServletContainer.java:121) - Jetty started on port(s) 8083 (http/1.1), 8443 (ssl-http/1.1, http/1.1)JAVA 代碼讀取客戶端證書信息
在雙向認證開啟并且服務器信任客戶端證書的前提下,在服務端是可以通過代碼來讀取客戶端證書信息的,通過debug可以看出證書信息是保存在request對象中,如下圖示例:
此次開發(fā)過程中用戶信息是保存在證書的CN字段中,具體情況依據(jù)證書的不同有區(qū)別,但都會保存在這個X509Certificate對象中。
完整代碼如下:
String scheme = request.getScheme(); if (scheme.equalsIgnoreCase(HttpScheme.HTTP.asString())) { response.sendError(401, "當前請求只允許使用HTTPS方式,請聯(lián)系管理員"); return; } X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); if (certs == null) { LOG.info("從request對象中未獲取到證書信息"); response.sendError(401, "證書不存在或者未選擇證書!請插入數(shù)字證書,重啟瀏覽器后再點擊訪問!"); return; } X509Certificate gaX509Cert = certs[0]; gaX509Cert.checkValidity(new Date());ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(gaX509Cert.getEncoded()); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate newGaX509Cert = (X509Certificate) cf.generateCertificate(byteArrayInputStream); byteArrayInputStream.close(); String dn = newGaX509Cert.getSubjectDN().toString(); LOG.info("證書DN項包括姓名、身份證號碼等信息:" + dn); String cn = dn.substring(3, dn.indexOf(',')); String[] nameAndCid = cn.split(" "); String name = nameAndCid[0]; String cid = nameAndCid[1];參考: 一篇文章看明白 HTTP,HTTPS,SSL/TSL 之間的關系
參考: HTTPS加密協(xié)議詳解(三):PKI 體系(沃通Wosign證書官網FAQ,鏈接放不了,有興趣可以自己直接進官網看)書有未曾經我讀,事無不可對人言
posted on 2020-07-28 14:04 precedeforetime 閱讀(1670) 評論(0) 編輯 收藏 舉報
刷新評論
刷新頁面
返回頂部導航
- 博客園
</li> <li>
首頁
</li>
<li>
新隨筆
</li>
<li>
聯(lián)系
- 訂閱
- 管理
</li><a id="footer_site_link">博客園</a> <br /> Copyright © 2021 precedeforetimePowered by .NET 5.0 on Kubernetes
<input type="hidden" id="antiforgery_token" value="CfDJ8NACB8VE9qlHm6Ujjqxvg5CAZx05dFmQJ0-9xKTp2ZnnE5GQNgoUb0-9VBG4MLeO1izOBBO7R3qawz10CVuWxFSdp6cQf1dYRuUabN_9vgMcL0CKU8yvJT9mve7JChSyq0aP_euyaYFmZEuAhOnjCLY" />
總結
以上是生活随笔為你收集整理的PKI体系详解_基于PKI体系的认证方式进行论述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3DSMax如何制作红色的橱柜
- 下一篇: 【idea】推荐一个idea翻译插件:T