最近實習需要寫一些生成證書的腳本,借此機會順便搞清楚了許多關于證書這塊的疑惑。說到這一塊東西,名詞多到爆炸,對稱加密、非對稱加密、密鑰、密鑰庫、公鑰、私鑰、CA、證書、數字簽名、ssh、https、ssl、keytool、openssl、PKCS、X.509以及令人眼花繚亂的文件后綴名,cer、crt、pem、keystore、jks、key、p12、pfx...
先聽我講個故事,這次我們不用Bob和Alice,聽完之后再去看這些概念,絕壁恍然大悟。
故事背景:這是2018年,為了能夠安全的進行通信,假設每個人都有倆把鎖,一個叫A鎖,一個叫B鎖,這倆把鎖和一般的鎖有點區別,每把鎖上即帶有自己的鎖孔又帶有另一把鎖的鑰匙,因此A鎖和B鎖既是鎖又是鑰匙。A鎖和B鎖唯一配對,A鎖鎖住之后,只有B鎖可以打開,同樣B鎖鎖住之后,只有A鎖可以打開。其中一把鎖是公開的,而一把鎖則自己保管,不公開。假設默認A鎖是公開的,B鎖是私有的。
故事內容:阿里巴巴子弟小學的小明想給隔壁班的小花寫封表白信,為了不被別人看到,他將信放入在信箱中,并用小花的A鎖將信箱鎖住,因為小花的B鎖(同是A鎖的鑰匙)只有小花自己有,所以除了小花以外的任何人拿到信件,都無法看到信件內容。同樣小花要給小明寫信,那么也要用小明的A鎖對信件內容進行保護。
小明與小花通過就這樣聊了有一段時間,后來小花覺得差不多了,可以進入秀恩愛的階段了,跟小明說,以后寫信別tm加密了,又不是銀行卡密碼,被人看到又能怎么樣呢?只要看了之后別瞎改就行了。于是小明在寫完信后,把信里每個字的拼音首字母拼湊了一個字符串,并取名為消息摘要,然后僅僅將消息摘要放入信箱,用自己的B鎖鎖住這個信箱。雖然信件本身沒有放入安全的信箱,但小明作為一個情書高手,隨便一封信都是上萬字,如果其他人對信件內容做任何改變,那么拼音首字母組成的字符串幾乎肯定會改變,因此小花拿到信件后,先用小明的A鎖(B鎖的鑰匙)打開信箱,拿到小明的摘要,然后小花再對信件內容做同樣的處理(即計算信件每個字的拼音首字母,實際上不會用這么簡單的算法,而是會用不可逆的hash算法),計算出的字符串值如與小明的信息摘要一致,說明這封信就是小明寫給自己的,沒有被任何人篡改。
故事高潮:事情并沒有那么簡單,小花發現小明只是在信件里對自己熱情似火,平常見了面連聲招呼都不打,一副不認識的樣子。終于有一天小花忍不住了,當面質問小明,小明卻說,我什么時候給你寫情書了,自作多情吧...于是小花把昨天剛收到的情書狠狠甩在了小明臉上:“上面落款不是你小明嗎?怎么了,慫了?”小明一看上面還真是自己的名字,但是自己寫沒寫信自己還不知道嗎?小明把自己的作業本拿給小花,并叫自己的同桌做筆跡鑒定,小花發現筆跡的確不大像,看來是有人惡作劇,冒充小明給自己寫情書,哎,好尷尬啊。。。
故事講完了,文章開頭涉及的所有概念都與信息的安全傳輸有關,可以說,一切都是為了安全。關于通信安全,我們通常有三個基本的需求
- 通信的數據本身是被加密的,第三方即使拿到了數據,也是無法輕易破解的密文。
- 通信的數據本身不加密,但是可以確保內容不被篡改
- 能夠驗證通信方身份
我們以上面的故事為例說一下這三點安全需求,一開始小明與小花通過A鎖(對應公鑰)加密,B鎖(對應私鑰)解密的通信方式即符合第一點,信件內容本身被加密,而因為公私鑰唯一配對,只有配對的密鑰才可以解密,因此很難被第三人破解。
之后,為了秀恩愛,他們采用了B鎖(私鑰)加密,A鎖(公鑰)解密的通信方式,其中用私鑰對消息摘要加密后的字符串稱為數字簽名,這樣雖然信件可以被人直接看到,但如果被人篡改掉后可以輕易發現數據被篡改。本來以為滿足第一條和第二條就可以安全的通信了,但最后才發現小明根本不是小明!為什么會出現這樣的問題?因為“小明”說他是小明,小花就以為他是小明,他沒有提供任何證明自己真的是小明的認證。因此要想安全通信,我們還需要一個權威第三方的機構來做身份認證,這個機構就是CA機構,通過認證后,CA機構會頒發權威的證書,而有了證書就可以證明身份,就不會出現身份被假冒的情況。而認證的過程則需要向CA機構提供自己的身份信息以及私鑰。
對稱加密 VS 非對稱加密
對稱加密就是通信雙方或多方采用的密鑰是一樣的。加解密速度快,但不夠安全。因為一旦密鑰泄露,誰都可以對數據進行解密。非對稱加密就是當然就是通信雙方使用的密鑰不同。而公鑰和私鑰就是非對稱加密的一種方式。比較常用的對稱加密算法如
AES、DES,非對稱加密比較常見的則有sha256,RSA。
非對稱加密算法有倆個密鑰,一個公鑰,一個私鑰。公鑰和私鑰必須配對出現,一對公鑰和一個私鑰統稱為一個密鑰,而密鑰庫中可以存放多個密鑰,即多對公私鑰。
- 公鑰是公開的,私鑰是保存在自己本地的
- 通信雙方各有一套公鑰和私鑰
- 公鑰加密的數據只有私鑰可以解密
- 私鑰加密的數據只有公鑰可以解密
如果你用github的話,應該注意到github鏈接有倆種方式。一種是https,一種是ssh,通過https經常需要輸密碼,而通過ssh則不需要。回憶你設置ssh的步驟,本地生成了一個密鑰對,并將公鑰上傳到了github。每次傳輸用自動本地私鑰加密,服務器用你上傳的公鑰解密,就不需要手動輸入密碼了。
keytool VS openssl
keytool和openssl是倆個證書管理工具.keytool是java JDK自帶的證書管理工具,使用keytool可以生成密鑰,創建證書。只要裝了jdk,并正確設置了環境變量,就可以之間通過命令行執行keytool命令來管理證書。
openssl則是一個開源的安全套接字層密碼庫,功能比keytool更加豐富。
X.509 VS PKCS
PKCS全稱Public-Key Cryptography Standards 即公鑰標準,PKCS已經發布了15個標準。
PKCS#12 包含了公鑰和私鑰的二進制格式的證書形式,以pfx作為證書文件后綴
X.509 則是一個通用的證書標準,規定了證書應該包含哪些內容,X.509通常有倆種編碼方式,一種是二進制編碼,另一種是base64編碼
X.509#DER 二進制格式證書,常用后綴.cer .crt
X.509#PEM 文本格式證書,常用后綴.pem
ssl vs https
因為http是明文傳輸,非常不安全,因此又提出了ssl(Secure Sockets Layer即安全套接字)層協議,即在原來的基礎上又加了一層協議用于保障安全傳輸,可以認為https=ssl+http。很多人剛開始接觸https,用瀏覽器F12打開控制臺后。可能發現數據仍然沒有加密。要注意https是傳輸層加密,瀏覽器F12控制臺你看到的還是應用層的數據。
因為本文主要是概念掃盲,幫助理解,因此關于這部分具體細節不作介紹。
各種常見文件后綴
.keystore和.jks和.truststore都是java用來存放密鑰的文件
.key nginx中私鑰文件
而不同的證書文件后綴都是為了區分不同種類的證書的,主要有倆個分類維度
- 證書內容是只包含公鑰,還是即包含公鑰又包含私鑰
如.pfx 和 .p12 即包含公鑰又包含私鑰
.crt、.cer、.pem只包含公鑰 - 通過編碼格式來區分
通常.crt和.cer為二進制編碼
.pem為base64編碼
不同的證書格式之間有時候需要轉換,用到時候查對應的openssl或keytool命令就好了。