關(guān)于證書,這里有你想知道的一切
概覽

術(shù)語
下列的某些術(shù)語其實在Java的權(quán)限控制框架中也經(jīng)常見到;
實體(entity)
entity可以是任何東西,即使是虛擬的,例如:
每個人類個體是一個entity;
你的計算機也是一個entity;
一個小狗是一個entity;
甚至神話傳說中的孫悟空等也可以是一個entity;
身份(identity)
官方定義:一個或多個實體以一個或多個屬性的形式表示的一個實體,這些屬性允許實體在上下文中充分區(qū)分;
舉例:例如你在學(xué)校,是一個學(xué)生xxx的身份,而你在家里,又是子女的身份;更細(xì)化一些,你在學(xué)校,身高185,長像彭于晏,那你就是標(biāo)準(zhǔn)的帥哥同學(xué)的身份;
身份標(biāo)識符(identifier)
身份標(biāo)識符被定義為一系列數(shù)字、字符和符號或任何其他形式的數(shù)據(jù),這些數(shù)據(jù)可以用來識別各個entity;一個身份可能會對應(yīng)多個entity,但是一個身份標(biāo)識符會唯一對應(yīng)一個entity,例如學(xué)校里邊學(xué)生身份的人很多,但是學(xué)號是xxx的學(xué)生只有一個;
聲明(claim)和認(rèn)證(authentication)
一個實體可以聲明(claim)說他擁有某些東西,而其他實體能對這個聲明進(jìn)行認(rèn)證(authenticate),以確認(rèn)聲明的真實性;通常認(rèn)證的目的就是確認(rèn)聲明的合法性;
subscriber & CA & relying party(RP)
能作為一個證書的subject的entity,稱為subscriber(證書owner)或者end entity;
對應(yīng)地,subscriber 的證書有時也稱為 end entity certificates 或 leaf certificates, 原因在后面討論 certificate chains 時會介紹。
CA(certificate authority,證書權(quán)威)是給 subscriber 頒發(fā)證書的實體,是一種 certificate issuer(證書頒發(fā)者)。
CA 的證書,通常稱為root certificate或 intermediate certificate,具體取決于 CA 類型。
Relying party 是使用證書的用戶(certificate user),它驗證由 CA 頒發(fā)(給 subscriber)的證書是否合法。
一個 entity 可以同時是一個 subscriber 和一個 relying party。也就是說,單個 entity 既有自己的證書,又使用其他證書來認(rèn)證 remote peers, 例如雙向 TLS(mutual TLS,mTLS)場景。
公鑰加密(Public key cryptography)及PKCS
證書(certificate)和PKI的基礎(chǔ)是公鑰加密(public key cryptography),也叫非對稱加密(asymmetric cryptography);
公鑰加密的理論基礎(chǔ)非常復(fù)雜,但是如果只是使用,我們并不需要了解其每一步數(shù)學(xué)原理,只需要知道其能做什么即可;
PKCS
我們可以在很多地方看到PKCS,PKCS是公鑰加密標(biāo)準(zhǔn),PKCS全稱是Public-Key Cryptography Standards,由RSA實驗室與其他安全系統(tǒng)開發(fā)商為促進(jìn)公鑰加密的發(fā)展而定制的一系列標(biāo)準(zhǔn),PKCS目前共發(fā)布過15個標(biāo)準(zhǔn):
PKCS#1:RSA Cryptography Standard,定義了RSA Public Key和Private Key數(shù)學(xué)屬性和格式。詳見RFC8017;
PKCS#3:定義Diffie-Hellman密鑰交換協(xié)議。
PKCS#5:描述一種利用從口令派生出來的安全密鑰加密字符串的方法。使用MD2或MD5 從口令中派生密鑰,并采用DES-CBC模式加密。主要用于加密從一個計算機傳送到另一個計算機的私人密鑰,不能用于加密消息。
PKCS#6:描述了公鑰證書的標(biāo)準(zhǔn)語法,主要描述X.509證書的擴展格式。
PKCS#7:定義一種通用的消息語法,包括數(shù)字簽名和加密等用于增強的加密機制,PKCS#7與PEM兼容,所以不需其他密碼操作,就可以將加密的消息轉(zhuǎn)換成PEM消息。常用的后綴是:.P7B .P7C .SPC;PKCS#7以樹狀展示證書鏈,同時也支持單個證書;
PKCS#8:描述私有密鑰信息格式,該信息包括公開密鑰算法的私有密鑰以及可選的屬性集等。詳見RFC5858;
PKCS#9:定義一些用于PKCS#6證書擴展、PKCS#7數(shù)字簽名和PKCS#8私鑰加密信息的屬性類型。
PKCS#10:描述證書請求語法(CSR)。
PKCS#11:稱為Cyptoki,定義了一套獨立于技術(shù)的程序設(shè)計接口,用于智能卡和PCMCIA卡之類的加密設(shè)備。
PKCS#12:描述個人信息交換語法標(biāo)準(zhǔn)。描述了將用戶公鑰、私鑰、證書和其他相關(guān)信息打包的語法,定義了通常用于存儲公鑰/私鑰的文件格式,使用基于密碼的對稱密鑰進(jìn)行保護(hù),PKCS#12文件實際上是一個KeyStore,詳見RFC292。常用的后綴有:.P12 .PFX;PS:通常Java中使用的jks文件屬于Java自己定義的格式與p12文件可以互相轉(zhuǎn)換,但是不能直接使用;
PKCS#13:橢圓曲線密碼體制標(biāo)準(zhǔn)。
PKCS#14:偽隨機數(shù)生成標(biāo)準(zhǔn)。
PKCS#15:密碼令牌信息格式標(biāo)準(zhǔn)。
密鑰對
公鑰加密系統(tǒng)使用密鑰對(key pair)來加解密,一個密鑰對包含:
一個私鑰,解密用,不能公開;
一個公鑰,可以分發(fā)給任何人,加密用;
密鑰可以做的事情:
加解密;公鑰加密私鑰解密;
簽名:私鑰簽名公鑰驗簽;
公鑰加密解決的問題
在沒有公鑰加密只有對稱加密的時候,如果我們想要在不安全的網(wǎng)絡(luò)上互相安全的通信,則需要將我們的消息加密,加密就需要交換密鑰,而由于網(wǎng)絡(luò)是一個不安全的信道,如果我們在網(wǎng)絡(luò)上直接交換密鑰可能會被惡意攻擊者截獲,一旦密鑰被截獲,惡意攻擊者就能隨時解密我們的消息,而使用公鑰加密就不存在該問題,我們可以大膽的將公鑰在網(wǎng)絡(luò)上分發(fā)給別人,而不用擔(dān)心其被截獲,因為公鑰加密的內(nèi)容只有私鑰能解密,而私鑰只有我們自己有;
用一句話概括:公鑰加密解決了在不安全信道上如何交換密鑰的問題;
實際應(yīng)用中密鑰交換不僅僅是將公鑰分發(fā)出去這么簡單,詳細(xì)可以參考通過局域網(wǎng)中間人攻擊學(xué)網(wǎng)絡(luò)第四篇
證書
前邊說到如果想要在不安全的網(wǎng)絡(luò)上實現(xiàn)安全通信,需要用到公鑰加密,把公鑰給別人,而僅僅是公鑰給別人的話包含的信息又太少了,比如如果別人想要知道你是誰,這個在公鑰上是沒辦法得到的,而證書則解決了這個問題,證書規(guī)定了在交換公鑰的時候還應(yīng)該給別人哪些信息,這里證書其實是一個包含公鑰的數(shù)據(jù)結(jié)構(gòu),描述了里邊包含的內(nèi)容,例如包含公鑰、姓名/公司名等;
雖然證書中已經(jīng)包含了公鑰信息和所有者等信息,我們可以將證書分發(fā)給其他人來進(jìn)行安全通信,但是如何讓別人信任這個證書的信息呢?即如何給使用者證明這個證書就是你的,而不是其他人偽造的,這就引入了權(quán)威機構(gòu)(CA)的概念,假設(shè)我們兩個都信任一個權(quán)威結(jié)構(gòu),那么我們可以讓權(quán)威機構(gòu)給我們的證書進(jìn)行簽名,然后將簽名附加到證書中,這樣使用者就可以對簽名進(jìn)行校驗,如果是其信任的權(quán)威機構(gòu)的簽名則認(rèn)為證書的信息是真實的;
總結(jié)來說,證書就是將名字(和其他一些信息)關(guān)聯(lián)到公鑰上的東西;
PS:權(quán)威機構(gòu)就類似公安機關(guān),我們經(jīng)常會從網(wǎng)上看到一些奇葩新聞,即某些機構(gòu)要求證明你就是你,而證明方法就是讓公安機關(guān)開具證明,這里公安機關(guān)就類似一個權(quán)威機構(gòu);
X.509證書
一般來說,當(dāng)我們提到證書一詞,并且沒有添加額外的限定詞時,指的都是X.509 v3證書,更準(zhǔn)確地說,他們指的是RFC5280中描述、 CA/Browser Forum Baseline Requirements中進(jìn)一步完善的 PKIX 變種。所以當(dāng)你看到PKIX Certificate字樣的時候可以認(rèn)為就是X.509 Certificate。
證書中提到了證書就是將名字等信息關(guān)聯(lián)到公鑰上的東西,證書實際上就是一個包含公鑰的數(shù)據(jù)結(jié)構(gòu),而證書中都有哪些信息則是更具體的規(guī)范中定義的,我們最常用的就是X.509 v3證書規(guī)范;
歷史簡介:X.509 在1988年作為國際電信聯(lián)盟(ITU)X.500 項目的一部分首次標(biāo)準(zhǔn)化。這是通信(telecom)領(lǐng)域的標(biāo)準(zhǔn),想通過它構(gòu)建一個全球電話簿(global telephone book)。雖然這個項目沒有成功,但卻留下了一些遺產(chǎn),X.509 就是其中之一;如果查看 X.509 的證書,會看到其中包含了 locality、state、country 等信息, 之前可能會有疑問為什么為 web 設(shè)計的證書會有這些東西,現(xiàn)在應(yīng)該明白了,因為X.509 并不是為 web 設(shè)計的。
X.509 v3證書是構(gòu)建在ASN.1編碼規(guī)范上的,ASN.1編碼規(guī)范后續(xù)介紹;
X.509常見后綴:
X.509 DER 編碼(ASCII)的后綴是:.DER .CER .CRT
X.509 PAM 編碼(Base64)的后綴是:.PEM .CER .CRT
ASN.1編碼
ASN.1是一種用來定義數(shù)據(jù)結(jié)構(gòu)的接口描述語言,它不是二進(jìn)制,也不是文件格式,本身只定義了表示信息的抽象句法;標(biāo)準(zhǔn)ASN.1編碼規(guī)則有BER(Basic Encoding Rules)、CER(Canonical Encoding Rules)、DER(Distinguished Encoding Rules)、PER(Packed Encoding Rules)、XER(XML Encoding Rules);
也就是說ASN.1是來描述一個事物的,例如用ASN.1來定義一個人,包含姓名、身高、性別等屬性,但是如何將這些數(shù)據(jù)傳給別人,就需要具體的編碼規(guī)則了,具體的編碼規(guī)則再將這些信息轉(zhuǎn)換為可傳輸?shù)亩M(jìn)制數(shù)據(jù)來傳輸給別人;更貼近點兒我們的代碼,就像你有一個內(nèi)存實體,在遠(yuǎn)程調(diào)用的時候需要傳給別人,那你就要定義這個實體如何序列化,這樣接收方才能接收,例如你用protocol buf來傳輸,而在這里,ASN.1就相當(dāng)于這個內(nèi)存實體的定義,而具體的編碼規(guī)則則相當(dāng)于protocol buf;
PEM
PEM是一個用來存儲和發(fā)送密碼學(xué)key、證書和其他數(shù)據(jù)的文件格式的事實標(biāo)準(zhǔn)。許多使用ASN.1的密碼學(xué)標(biāo)準(zhǔn)(比如X.509和PKCS)都使用DER編碼,而DER編碼的內(nèi)容是二進(jìn)制的,不適合與郵件傳輸(早期Email不能發(fā)送附件),因此使用PEM把二進(jìn)制內(nèi)容轉(zhuǎn)換成ASCII碼。文件內(nèi)容的格式像下面這樣:
-----BEGIN label-----
BASE64Encoded
-----END label-----
label用于區(qū)分內(nèi)容到底是什么類型,與PEM相關(guān)的RFC有很多,與文本相關(guān)的是RFC7468,里邊規(guī)定了很多l(xiāng)abel;注意,不是所有l(wèi)abel都有對應(yīng)的RFC,這些label只是一種約定俗成;
PEM實際上就是把DER編碼的文件的二進(jìn)制內(nèi)容用base64編碼一下,然后加上-----BEGIN label-----這樣的頭和-----END label-----這樣的尾,中間則是DER文件的Base64編碼。
不幸的是,即使是這樣簡單的規(guī)范,其中的label并不統(tǒng)一,相同的內(nèi)容在不同的實現(xiàn)下label可能并不一致;
PKI
公鑰基礎(chǔ)設(shè)施(PKI, 全稱 public key infrastructure)是創(chuàng)建、管理、分發(fā)、使用、存儲和撤銷數(shù)字證書以及管理公鑰加密所需的一組角色、策略、硬件、軟件和過程。
證書是大部分PKI的構(gòu)建模塊,而證書權(quán)威是其基礎(chǔ);
自己從頭構(gòu)建PKI是一件極其龐大的工作,但實際上一些簡單的PKI甚至并不使用證書,例如:
編輯~/.ssh/authorized_keys文件時,就是在配置 一個簡單的無證書形式的(certificate-less)PKI,SSH 通過這種方式在扁平文件內(nèi)實現(xiàn) public key 和 name 的綁定;
PGP 用證書,但不用 CA,而是用一個 web-of-trust model;
trust store
通過前面的介紹,證書可以解讀為一個claim,Issuer 會對這份聲明進(jìn)行簽名,relying party 能(通過 issuer 的公鑰)驗證(authenticate)簽名是否合法。但這里其實跳過了一個重要問題:relying party 是如何知道 issuer 的公鑰的?
答案其實很簡單,就是relying parties在自己的trust store(信任庫)預(yù)置了一個他信任的根證書列表;
當(dāng)我們添加自簽名證書到信任列表中時,就是將其添加到我們系統(tǒng)的trust store中;
作者微信:JoeKerouac
微信公眾號(文章會第一時間更新到公眾號,如果搜不出來可能是改名字了,加微信即可=_=|):代碼深度研究院
GitHub:https://github.com/JoeKerouac
