證書標(biāo)準(zhǔn)
X.509 - 這是一種證書標(biāo)準(zhǔn),主要定義了證書中應(yīng)該包含哪些內(nèi)容.其詳情可以參考RFC5280,SSL使用的就是這種證書標(biāo)準(zhǔn).
-
編碼格式
同樣的X.509證書,可能有不同的編碼格式,目前有以下兩種編碼格式.
<b>PEM - Privacy Enhanced Mail:</b> 打開看文本格式,以"-----BEGIN..."開頭, "-----END..."結(jié)尾,內(nèi)容是base64編碼。
查看PEM格式證書的信息:
openssl x509 -in certificate.pem -text -noout
Apache和Nginx服務(wù)器偏向于使用這種編碼格式.
<b>DER - Distinguished Encoding Rules</b> :打開看是二進制格式(ASCII編碼),不可讀.
查看DER格式證書的信息:
openssl x509 -in certificate.der -inform der -text -noout
Java和Windows服務(wù)器偏向于使用這種編碼格式.
<b>相關(guān)的文件擴展名
這是比較誤導(dǎo)人的地方,雖然我們已經(jīng)知道有PEM和DER這兩種編碼格式,但文件擴展名并不一定就叫"PEM"或者"DER",常見的擴展名除了PEM和DER還有以下這些,它們除了編碼格式可能不同之外,內(nèi)容也有差別,但大多數(shù)都能相互轉(zhuǎn)換編碼格式.</b>
<b>CRT</b> - CRT應(yīng)該是certificate的三個字母,其實還是證書的意思,常見于Nginx系統(tǒng),有可能是PEM編碼,也有可能是DER編碼,大多數(shù)應(yīng)該是PEM編碼,相信你已經(jīng)知道怎么辨別.
<b>CER </b> - 還是certificate,還是證書,常見于Windows系統(tǒng),同樣的,可能是PEM編碼,也可能是DER編碼,大多數(shù)應(yīng)該是DER編碼.
<b>KEY</b> - 通常用來存放一個公鑰或者私鑰,并非X.509證書,編碼同樣的,可能是PEM,也可能是DER.
查看KEY的辦法:
openssl rsa -in mykey.key -text -noout
如果是DER格式的話,同理應(yīng)該這樣了:
openssl rsa -in mykey.key -text -noout -inform der
<b>CSR</b> - Certificate Signing Request,即證書簽名請求,這個并不是證書,而是向權(quán)威證書頒發(fā)機構(gòu)獲得簽名證書的申請,其核心內(nèi)容是一個公鑰(當(dāng)然還附帶了一些別的信息),在生成這個申請的時候,同時也會生成一個私鑰,私鑰要自己保管好.做過iOS APP的朋友都應(yīng)該知道是怎么向蘋果申請開發(fā)者證書的吧.
查看的辦法:
openssl req -noout -text -in my.csr
(如果是DER格式的話照舊加上-inform der,這里不寫了)
<b>PFX/P12</b> - predecessor of PKCS#12,對Nginx服務(wù)器來說,一般CRT和KEY是分開存放在不同文件中的,但Windows的IIS則將它們存在一個PFX文件中,(因此這個文件包含了證書及私鑰)這樣會不會不安全?應(yīng)該不會,PFX通常會有一個"提取密碼",你想把里面的東西讀取出來的話,它就要求你提供提取密碼,PFX使用的是DER編碼即ASCII編碼,如何把PFX轉(zhuǎn)換為PEM編碼?
openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes
只提取證書
openssl pkcs12 -nokeys -in cacert.p12 -out ca2cert.pem
只提取秘鑰對
openssl pkcs12 -nocerts -in cacert.p12 -out ca2cert.pem
使用-export提示你輸入提取代碼,否則直接報錯廊蜒。
生成pfx/p12的命令類似這樣:
openssl pkcs12 -export -out certificate.pfx/p12 -inkey privateKey.key -in certificate.crt -certfile CACert.crt
其中CACert.crt是CA(權(quán)威證書頒發(fā)機構(gòu))的根證書,有的話也通過-certfile參數(shù)一起帶進去.這么看來,PFX其實是個證書密鑰庫,這樣通過鑰匙串就能看到鏈結(jié)構(gòu)封字。
<b>JKS</b> - 即Java Key Storage,這是Java的專利,跟OpenSSL關(guān)系不大,利用Java的一個叫"keytool"的工具,可以將PFX轉(zhuǎn)為JKS,當(dāng)然了,keytool也能直接生成JKS,不過在此就不多表了.
證書編碼的轉(zhuǎn)換
PEM轉(zhuǎn)為DER openssl x509 -in cert.crt -outform der -out cert.der
DER轉(zhuǎn)為PEM openssl x509 -in cert.crt -inform der -outform pem -out cert.pem
(提示:要轉(zhuǎn)換KEY文件也類似,只不過把x509換成rsa,要轉(zhuǎn)CSR的話,把x509換成req...)
<b>獲得證書向權(quán)威證書頒發(fā)機構(gòu)申請證書
用這命令生成一個 </b>
csr: openssl req -newkey rsa:2048 -new -nodes -keyout my.key -out my.csr
把csr交給權(quán)威證書頒發(fā)機構(gòu),權(quán)威證書頒發(fā)機構(gòu)對此進行簽名,完成.保留好csr,當(dāng)權(quán)威證書頒發(fā)機構(gòu)頒發(fā)的證書過期的時候,你還可以用同樣的csr來申請新的證書,key保持不變.
<b>或者生成自簽名的證書</b>
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
在生成證書的過程中會要你填一堆的東西,其實真正要填的只有Common Name,通常填寫你服務(wù)器的域名,如"yourcompany.com",或者你服務(wù)器的IP地址,其它都可以留空的.
生產(chǎn)環(huán)境中還是不要使用自簽的證書,否則瀏覽器會不認,或者如果你是企業(yè)應(yīng)用的話能夠強制讓用戶的瀏覽器接受你的自簽證書也行.向權(quán)威機構(gòu)要證書通常是要錢的,但現(xiàn)在也有免費的,僅僅需要一個簡單的域名驗證即可.有興趣的話查查"沃通數(shù)字證書".
自簽名的證書
-
首先我們需要建好CA目錄
> mkdir -p ./demoCA/{private,newcerts} > touch ./demoCA/index.txt > echo 01 > ./demoCA/serial
其中我們使用private 文件夾下得cakey.pem(配置文件的默認文件名敦冬,如果不知道當(dāng)前系統(tǒng)openssl的配置文件的位置艰垂,可以使用 >openssl ca 命令) 秘鑰對或者使用-keyfile 指定private文件下的其他秘鑰對來給二級或其他證書數(shù)字簽名。
我們有兩種方式生成根證書
第一種:這種方式不用自己生成秘鑰番甩,不用生成多余的證書請求文件,干凈届搁!
(這里我么使用自動生成秘鑰對缘薛,采用配置文件默認秘鑰對名稱cakey.pem ,方便后面使用卡睦,當(dāng)然你也可以使用其他名字 宴胧,后面用-keyfile指定就OK了,過期時間不指定默認是30天)
$ openssl req -x509 -days 3560 -newkey rsa:2048 -keyout ./demoCA/private/cakey.pem -out cacert.pem
第二種:我么不推薦使用這種方式,也不建議使用明文方式的傳入密碼給秘鑰加密么翰。
$ openssl genrsa -des3 -passout pass:xuhaiqing -out ./demoCA/private/cakey.pem 2048
$ openssl req -new -days 3650 -key ./demoCA/private/cakey.pem -out careq.pem -passin pass:xuhaiqing
$ openssl ca -selfsign -in careq.pem -out cacert.pem
接下來我們使用生成的根證書來簽發(fā)證書
$ openssl genrsa -out userkey.pem
$ openssl req -new -days 3560 -key userkey.pem -out userreq.pem
$ openssl ca -in userreq.pem -out usercert.pem -keyfile cakey.pem -cert cacert.pem -policy policy_anything -extensions va_03
- -policy 指定簽發(fā)策policy_anything牺汤,表示任何內(nèi)容都可以,配置文件默認為policy_match,就是子簽發(fā)證書的國家,城市等要與上一級匹配相等浩嫌。
- -extensions va_03 是子簽發(fā)證書能夠再次簽發(fā)子證書檐迟,默認是子證書是不能再簽發(fā)。查看配置文件x509_extensions = usr_cert码耐,而usr_cert 的 basicConstraints=CA:FALSE追迟,基本約束為false,我們可以修改為basicConstraints=CA:true骚腥,或者x509_extensions = v3_ca,以為v3_ca 的 basicConstraints=CA:true敦间。
然后有人想導(dǎo)出公鑰,有兩種方式:
第一種從證書:$openssl x509 -in cacert.pem -pubkey -nonout > capubkey.pem
第二種從秘鑰:$openssl rsa -in cakey,pem -pubout -out capubkey.pem
補充
RSA加密&解密&簽名&驗證
-
產(chǎn)生1024位RSA私匙,用3DES加密它廓块,口令為trousers厢绝,輸出到文件rsaprivatekey.pem
$ openssl genrsa -out rsaprivatekey.pem -passout pass:trousers -des3 1024
-
重置口令,去除3DES加密
$openssl rsa -in rsaprivatekey.pem -out rsaprivatekey.pem
-
重置口令,添加其他加密
$openssl rsa -in rsaprivatekey.pem -passout pass:yourpassword -out -aes128|-aes192|-aes256|-camellia128|-camellia192|-camellia256|-des|-des3|-idea rsaprivatekey.pem
-
從文件rsaprivatekey.pem讀取私匙带猴,用口令trousers解密昔汉, 生成的公鑰匙輸出到文件rsapublickey.pem
$ openssl rsa -in rsaprivatekey.pem -passin pass:trousers -pubout -out rsapubckey.pem
-
用公鑰匙rsapublickey.pem加密文件plain.txt, 輸出到文件cipher.txt
$ openssl rsautl -encrypt -pubin -inkey rsapublickey.pem -in plain.txt -out cipher.txt
-
用私鑰匙rsaprivatekey.pem加密文件plain.txt拴清, 輸出到文件cipher.txt(實際上系統(tǒng)會取私鑰里的公鑰來加密)
$ openssl rsautl -encrypt -inkey rsapublickey.pem -in plain.txt -out cipher.txt
-
使用私鑰匙rsaprivatekey.pem解密密文cipher.txt靶病,輸出到文件plain.txt
$ openssl rsautl -decrypt -inkey rsaprivatekey.pem -in cipher.txt -out plain.txt
-
用私鑰匙rsaprivatekey.pem給文件plain.txt簽名,輸出到文件signature.bin
$ openssl rsautl -sign -inkey rsaprivatekey.pem -in plain.txt -out signature.bin
-
用公鑰匙rsapublickey.pem驗證簽名signature.bin口予,輸出到文件plain.txt
$ openssl rsautl -verify -pubin -inkey rsapublickey.pem -in signature.bin -out plain
-
用私匙rsaprivatekey.pem驗證簽名signature.bin娄周,輸出到文件plain.txt(實際上系統(tǒng)會取私鑰里的公鑰來驗證)
$ openssl rsautl -verify -inkey rsapublickey.pem -in signature.bin -out plain