數字證書、公私鑰小記

術語

  • X.509java

在密碼學中,X.509是由ITU-T爲了公開密鑰基礎建設(PKI)與受權管理基礎建設(PMI)提出的產業標準。X.509標準,規範了公開密鑰認證、證書吊銷列表、受權證書、證書路徑驗證算法等。[1]node

  • PKCS(Public Key Cryptography Standards)算法

PKCS是由RSA公司制定的一組關於公鑰加密的標準,和存儲相關的主要包括:工具

PKCS1:定義了RSA的數理基礎、公私鑰格式,以及加解密、籤/驗章的流程
PKCS8:定義了私鑰消息的表示
PKCS12:定義了包含私鑰與公鑰證書的文件格式,其中私鑰採密碼保護

公私鑰及證書的生成

如下操做會用到opensslkeytool兩個工具。注意,若是不加聲明,證書和密鑰的存儲都是PEM格式。post

生成私鑰

openssl genrsa -out ca.key 2048

openssl生成的私鑰是按PKCS#1編碼的,這種格式包括了密鑰的全部信息(如n、e、d、p、q等)[2],因此genrsa只生成私鑰。ui

若是須要PKCS\#8編碼的私鑰,還須要額外的轉換:編碼

openssl pkcs8 -topk8 -inform PEM in ca.key -outform PEM -nocrypt -out ca.pkcs8.key

若是須要公鑰,須要使用以下的命令:加密

從私鑰獲得公鑰

openssl rsa -in ca.key -pubout -outform PEM -out ca.pub

生成的公鑰是按PKCS#8編碼的。大多數地方都採用這種格式表示公鑰。.net

生成根證書

openssl req -x509 -new -nodes -key ca.key -days 3000 -out ca.crt

生成的證書是按X.509編碼的,有效期是3000天。code

簽發證書

有了根證書,就能夠對證書籤名了。爲此,你須要先生成一個私鑰,例如叫作host.key,而後經過私鑰建立一個簽名請求(CSR):

openssl req -new -key host.key -out host.csr

openssl會問你一些問題,務必注意CN這個選項,它應當是放置該證書的主機名(域名或者IP地址),若是開啓了證書校驗,它必須跟客戶端創建鏈接時填寫的host一致。

有了CSR,就能夠用根證書和它的密鑰來簽發證書了:

openssl x509 -req -in host.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 1000 -out host.crt

證書依舊是按X.509編碼的,有效期是1000天。

證書格式的轉換

以上生成的公私鑰和證書都是PEM格式的,但不少時候不一樣場景中還須要用到其餘格式的證書:

p12/pfx

p12/pfx是按照PKCS#12編碼的對象,它一般由X.509證書和對應的私鑰組成。生成p12格式的方法以下:

openssl pkcs12 -export -in ca.crt -inkey ca.key -out ca.p12

因爲文件中保存了私鑰,所以執行該命令,openssl會要求用戶輸入密碼,用於保護私鑰。

jks

在Java中,免不了使用JKS格式,JKS是Java標準的密鑰和證書保存格式,嚴格來講,Java的KeyStore存儲的是多個密鑰和證書。要生成它,須要用到keytool工具:

p12文件轉換爲jks

keytool -importkeystore -srckeystore cert.p12 -srcstoretype pkcs12 -destkeystore cert.jks

分別輸入目標jks文件的密碼和源p12文件的密碼,便可生成。

crt文件轉換爲jks

keytool -import -file ca.crt -keystore ca.jks

不一樣環境/工具對密鑰的需求

Java

在Java中,若是要使用java.security包中和RSA相關的算法,你須要PKCS#8編碼的公私鑰,分別使用PKCS8EncodedKeySpecX509EncodedKeySpec加載Base64解碼後的數據便可。

若是要使用javax.net.ssl下的KeyStore或者TrustStore,最好使用jks格式,能夠省去不少麻煩。

CSharp

在.Net中,System.Security.Cryptography下的X509Certificate2X509Certificate已通過時了)使用p12格式。

一些問題

.Net 證書驗證

默認狀況下,.Net會對證書作很嚴格的檢驗,包括但不限於證書鏈、吊銷狀況,SSL/TLS中還會檢驗主機名。但對於自簽名證書,吊銷狀況是沒法經過檢查的,所以須要手動把吊銷檢驗關閉:

var chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.Build(yourCert);

Java 證書驗證

Java會本身維護一個證書鏈(位於JAVA_HOME/lib/security/cacerts),所以把證書加到系統的cacerts裏彷佛是無效的。對於 SSLContext,必需要本身把證書加到 TrustStore裏。須要指出的是,若是使用JSSE,Java是不會驗證主機名的,必須本身處理,這裏有討論。

參考資料



原文連接: https://dangfan.me/zh-Hans/posts/certificates
相關文章
相關標籤/搜索