X.509java
在密碼學中,X.509是由ITU-T爲了公開密鑰基礎建設(PKI)與受權管理基礎建設(PMI)提出的產業標準。X.509標準,規範了公開密鑰認證、證書吊銷列表、受權證書、證書路徑驗證算法等。[1]node
PKCS(Public Key Cryptography Standards)算法
PKCS是由RSA公司制定的一組關於公鑰加密的標準,和存儲相關的主要包括:工具
PKCS1:定義了RSA的數理基礎、公私鑰格式,以及加解密、籤/驗章的流程 PKCS8:定義了私鑰消息的表示 PKCS12:定義了包含私鑰與公鑰證書的文件格式,其中私鑰採密碼保護
如下操做會用到openssl
和keytool
兩個工具。注意,若是不加聲明,證書和密鑰的存儲都是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
是按照PKCS#12編碼的對象,它一般由X.509證書和對應的私鑰組成。生成p12
格式的方法以下:
openssl pkcs12 -export -in ca.crt -inkey ca.key -out ca.p12
因爲文件中保存了私鑰,所以執行該命令,openssl
會要求用戶輸入密碼,用於保護私鑰。
在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.security
包中和RSA相關的算法,你須要PKCS#8編碼的公私鑰,分別使用PKCS8EncodedKeySpec
和X509EncodedKeySpec
加載Base64解碼後的數據便可。
若是要使用javax.net.ssl
下的KeyStore
或者TrustStore
,最好使用jks
格式,能夠省去不少麻煩。
在.Net中,System.Security.Cryptography
下的X509Certificate2
(X509Certificate
已通過時了)使用p12
格式。
默認狀況下,.Net會對證書作很嚴格的檢驗,包括但不限於證書鏈、吊銷狀況,SSL/TLS中還會檢驗主機名。但對於自簽名證書,吊銷狀況是沒法經過檢查的,所以須要手動把吊銷檢驗關閉:
var chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.Build(yourCert);
Java會本身維護一個證書鏈(位於JAVA_HOME/lib/security/cacerts
),所以把證書加到系統的cacerts裏彷佛是無效的。對於 SSLContext
,必需要本身把證書加到 TrustStore
裏。須要指出的是,若是使用JSSE,Java是不會驗證主機名的,必須本身處理,這裏有討論。