|
目錄
前言
1 概念
2 環(huán)境
3 創(chuàng)建根證書CA
4 頒發(fā)證書
4.1 在需要證書的服務(wù)器上,生成證書簽署請求
4.2 在根證書服務(wù)器上,頒發(fā)證書
5 測試
5.1 讀取test.pfx文件
5.2 讀取test.cer文件
前言
最近,被分配了一個(gè)任務(wù),完成數(shù)字證書管理系統(tǒng)的開發(fā),一開始我是一臉懵逼的,因?yàn)橐郧拔覍τ谑裁磾?shù)字證書都沒了解過,可謂了一片空白,也不知其是用來干嘛的。于是,我奮發(fā)圖強(qiáng),用了一個(gè)下午加晚上的時(shí)間來腦補(bǔ)這部分概念知識,原來數(shù)字證書其實(shí)就是網(wǎng)站的身份認(rèn)證。
1 概念
數(shù)字證書是一個(gè)經(jīng)證書授權(quán)中心數(shù)字簽名的包含公開密鑰擁有者信息以及公開密鑰的文件。最簡單的證書包含一個(gè)公開密鑰、名稱以及證書授權(quán)中心的數(shù)字簽名。數(shù)字證書還有一個(gè)重要的特征就是只在特定的時(shí)間段內(nèi)有效。數(shù)字證書是一種權(quán)威性的電子文檔,可以由權(quán)威公正的第三方機(jī)構(gòu),即CA(例如中國各地方的CA公司)中心簽發(fā)的證書,也可以由企業(yè)級CA系統(tǒng)進(jìn)行簽發(fā)。
一般證書分有三類,根證書、服務(wù)器證書和客戶端證書。根證書,是生成服務(wù)器證書和客戶端證書的基礎(chǔ),是信任的源頭,也可以叫自簽發(fā)證書,即CA證書。服務(wù)器證書,由根證書簽發(fā),配置在服務(wù)器上的證書。客戶端證書,由根證書簽發(fā),配置在服務(wù)器上,并發(fā)送給客戶,讓客戶安裝在瀏覽器里的證書。
接下來,認(rèn)識了證書的基本概念之后,我們來認(rèn)識下這幾個(gè)概念,公鑰/私鑰/簽名/驗(yàn)證簽名/加密/解密/對稱加密/非對稱加密。
我們一般的加密是用一個(gè)密碼加密文件,然后解密也用同樣的密碼。這很好理解,這個(gè)是對稱加密。而有些加密時(shí),加密用的一個(gè)密碼,而解密用另外一組密碼,這個(gè)叫非對稱加密,意思就是加密解密的密碼不一樣。其實(shí)這是數(shù)學(xué)上的一個(gè)素?cái)?shù)積求因子的原理應(yīng)用,其結(jié)果就是用這一組密鑰中的一個(gè)來加密數(shù)據(jù),用另一個(gè)來解密,或許有人已經(jīng)想到了,沒錯(cuò)這就是所謂的公鑰和私鑰。公鑰和私鑰都可以用來加密數(shù)據(jù),而他們的區(qū)別是,公鑰是密鑰對中公開的部分,私鑰則是非公開的部分。公鑰加密數(shù)據(jù),然后私鑰解密的情況被稱為加密和解密;私鑰加密數(shù)據(jù),公鑰解密一般被稱為簽名和驗(yàn)證簽名。其中簽名和驗(yàn)證簽名就是我們本文需要說明和用到的,因?yàn)樽C書的生成過程中就需要簽名,而證書的使用則需要驗(yàn)證簽名。
2 環(huán)境
需要一個(gè)linux系統(tǒng)(一般centos 6以上或debian),一般linux系統(tǒng)是安裝了openssl的,若沒有安裝或嫌版本太低可參考https://blog.csdn.net/qq_15092079/article/details/81539889#2%20%E8%BD%AF%E4%BB%B6%E5%AE%89%E8%A3%85的openssl的安裝過程。
本文的linux系統(tǒng)是centos 7,openssl版本是OpenSSL 1.0.2k。可以通過以下命令來驗(yàn)證是否安裝了openssl,或者查看當(dāng)前openssl的版本。
openssl version -a
3 創(chuàng)建根證書CA
(1)查看openssl的配置文件openssl.cnf的存放位置(即openssl的安裝位置)
openssl version -a

(2)查看openssl的配置文件openssl.cnf,因?yàn)榕渲梦募袑ψC書的名稱和存放位置等相關(guān)信息都做了定義。
vim /etc/pki/tls/openssl.cnf


每個(gè)變量的后面都有英文注釋,懂英語的人應(yīng)該很容易就能理解相應(yīng)變量的意思,不懂英語的人可以直接百度搜索或者拿出你的英文翻譯器翻譯以下。
(3)創(chuàng)建為根證書CA所需的目錄及文件
#根據(jù)配置文件信息,到CA根目錄,若沒有則自己創(chuàng)建 #創(chuàng)建配置文件信息中所需的目錄及文件 mkdir -pv {certs,crl,newcerts,private}
(4)指明證書的開始編號
echo 01 >> serial
(5)生成根證書的私鑰(注意:私鑰的文件名與存放位置要與配置文件中的設(shè)置相匹配)。
(umask 077; openssl genrsa -out private/cakey.pem 2048)

參數(shù)說明:
genrsa --產(chǎn)生rsa密鑰命令
-aes256--使用AES算法(256位密鑰)對產(chǎn)生的私鑰加密,這里沒有此參數(shù),則只是用了rsa算法加密。
-out ---輸出路徑,這里指private/ca.key.pem
這里的參數(shù)2048,指的是密鑰的長度位數(shù),默認(rèn)長度為512位
(6)生成自簽證書,即根證書CA,自簽證書的存放位置也要與配置文件中的設(shè)置相匹配,生成證書時(shí)需要填寫相應(yīng)的信息。
openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out cacert.pem -days 365

參數(shù)說明:
-new:表示生成一個(gè)新證書簽署請求
-x509:專用于CA生成自簽證書,如果不是自簽證書則不需要此項(xiàng)
-key:用到的私鑰文件
-out:證書的保存路徑
-days:證書的有效期限,單位是day(天),默認(rèn)是openssl.cnf的default_days
這樣子,根證書CA就已經(jīng)生成完成了。

4 頒發(fā)證書
在需要證書的服務(wù)器上生成私鑰,然后通過此私鑰生成證書簽署請求,最后將請求通過可靠的方式發(fā)送給根證書CA的主機(jī)。根證書CA服務(wù)器在拿到證書簽署請求后,即可頒發(fā)那一服務(wù)器的證書。
4.1 在需要證書的服務(wù)器上,生成證書簽署請求
(1)生成私鑰,該私鑰的位置可隨意定
(umask 077; openssl genrsa -out test.key 2048)

具體的參數(shù)含義參考本文3的(5)處。
(2)生成證書簽署請求
openssl req -new -key test.key -out test.csr -days 365

具體的參數(shù)含義參考本文3的(6)處。
4.2 在根證書服務(wù)器上,頒發(fā)證書
(1)頒發(fā)證書,即簽名證書,生成crt文件
#我們創(chuàng)建一個(gè)req文件夾來接受服務(wù)器發(fā)送過來的文件(簽署請求的csr文件、key文件等) openssl ca -in /etc/pki/CA/req/test.csr -out /etc/pki/CA/certs/test.crt -days 365 openssl x509 -in /etc/pki/CA/certs/test.crt -noout -serial -subject

但是有些格式不是我們需要的,請看下面的兩個(gè)格式轉(zhuǎn)換。
(2)格式轉(zhuǎn)換為pfx格式的私鑰
openssl pkcs12 -export -out test.pfx -inkey /etc/pki/CA/req/test.key -in test.crt

注意,-inkey的值test.key是需要證書服務(wù)器上生成的私鑰key文件。
(3)格式轉(zhuǎn)換為cer格式的公鑰
openssl x509 -inform pem -in test.crt -outform der -out test.cer openssl x509 -in test.cer -text -noout #若報(bào)錯(cuò)unable to load certificate,則說明你打開的證書編碼是der格式,需要用以下命令 openssl x509 -in test.cer -inform der -text -noout

參數(shù)含義:
-inform pem,由于輸入的test.crt文件是以pem編碼的,故需要指定以pem編碼來讀取。
-outform der,輸出的test.cer文件需要以der編碼。
至此,服務(wù)器的證書頒發(fā)就完成了,只需要將此簽名證書發(fā)送給服務(wù)器,服務(wù)器就可以使用此簽名證書了。
5 測試
我們此處用java代碼來測試分別讀取test.pfx和test.cer文件的證書信息。
5.1 讀取test.pfx文件
import java.io.FileInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.Certificate; import java.util.Enumeration; public static void main(String[] args) throws Exception { String strPfx = "C:\\Users\\admin\\Desktop\\新建文件夾\\test.pfx"; String strPassword = "123"; KeyStore ks = KeyStore.getInstance("PKCS12"); FileInputStream fis = new FileInputStream(strPfx); // If the keystore password is empty(""), then we have to set // to null, otherwise it won't work!!! if ((strPassword == null) || strPassword.trim().equals("")) { nPassword = strPassword.toCharArray(); System.out.println("keystore type=" + ks.getType()); // Now we loop all the aliases, we need the alias to get keys. // It seems that this value is the "Friendly name" field in the // detals tab <-- Certificate window <-- view <-- Certificate // Button <-- Content tab <-- Internet Options <-- Tools menu Enumeration enumas = ks.aliases(); if (enumas.hasMoreElements())// we are readin just one certificate. keyAlias = (String) enumas.nextElement(); System.out.println("alias=[" + keyAlias + "]"); // Now once we know the alias, we could get the keys. System.out.println("is key entry=" + ks.isKeyEntry(keyAlias)); PrivateKey prikey = (PrivateKey) ks.getKey(keyAlias, nPassword); Certificate cert = ks.getCertificate(keyAlias); PublicKey pubkey = cert.getPublicKey(); System.out.println("cert class = " + cert.getClass().getName()); System.out.println("cert = " + cert); System.out.println("public key = " + pubkey); System.out.println("private key = " + prikey);
輸出結(jié)果展示,如下所示:
cert class = sun.security.x509.X509CertImpl Subject: EMAILADDRESS=test@test.com, CN=www.test.com, O=sky, ST=GuangDong, C=CN Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11 Key: Sun RSA public key, 2048 bits modulus: 22540549868269337731049045024507385260542573787628838370500488975031456915675928339191598608788978166412886818018144053254194317256993635868534742497106051883418262409480683986537120518762380588035635893822782045653063382717204771221158285234168172584993231255251797413350283828305540028023358503599723497159109886144323832651476034904177315494543160791317342173062905173635050774176310860122833148864737280742410768403748999912660341255531672554245341045495023594325494277633017114644620320127314817425829498919103113286133067466723376087306471415425209209026944245886309051331485179319181933688283658147367854481639 Validity: [From: Tue Aug 28 19:59:47 CST 2018, To: Wed Aug 28 19:59:47 CST 2019] Issuer: EMAILADDRESS=sky@sky.com, CN=localhost, O=sky, L=guangzhou, ST=GuangDong, C=CN Certificate Extensions: 4 [1]: ObjectId: 2.16.840.1.113730.1.13 Criticality=false Extension unknown: DER encoded OCTET string = 0000: 04 1F 16 1D 4F 70 65 6E 53 53 4C 20 47 65 6E 65 ....OpenSSL Gene 0010: 72 61 74 65 64 20 43 65 72 74 69 66 69 63 61 74 rated Certificat [2]: ObjectId: 2.5.29.35 Criticality=false 0000: 5C D9 0C CF D3 B8 76 6D CA AC B0 79 4E 2B 68 61 \.....vm...yN+ha [3]: ObjectId: 2.5.29.19 Criticality=false [4]: ObjectId: 2.5.29.14 Criticality=false 0000: 77 65 68 2C F7 8C 6A 03 E8 FF 7B BB 62 7C FB 63 weh,..j.....b..c Algorithm: [SHA256withRSA] 0000: 82 BC 07 E9 C5 E1 4A C4 88 AD 48 1C 71 68 0D 0E ......J...H.qh.. 0010: 09 0E 79 1D 86 22 ED 2D 34 AB 89 08 D3 4A E1 C2 ..y..".-4....J.. 0020: B9 04 82 BC CC 77 6B 71 87 F5 5F B7 F0 86 B5 D6 .....wkq.._..... 0030: CE 26 61 AC 33 96 F5 25 8A 64 32 75 CA CE E6 D2 .&a.3..%.d2u.... 0040: 83 A7 6D 43 21 18 60 0C F5 A7 2E 60 50 73 1E 26 ..mC!.`....`Ps.& 0050: 5F 89 04 55 E2 79 82 70 6C 36 05 B6 00 7D 6F 04 _..U.y.pl6....o. 0060: D8 75 CB D4 7B D6 0A 56 50 95 4A 8E 72 8D 43 C9 .u.....VP.J.r.C. 0070: 65 32 9F 9D 4A 63 6A 74 31 53 65 AC DF A6 B8 76 e2..Jcjt1Se....v 0080: 1D B3 C9 71 ED 38 77 16 AF 2D BD BB 40 A1 40 90 ...q.8w..-..@.@. 0090: 82 63 41 C7 84 4A 38 51 3E A2 AA 31 B4 5F 60 13 .cA..J8Q>..1._`. 00A0: 8D D4 7E 37 63 AE A7 5C 32 A5 09 18 A8 4D D7 69 ...7c..\2....M.i 00B0: CD 11 DF 17 28 07 3B 2D CA 76 E0 BA 59 A7 CB DE ....(.;-.v..Y... 00C0: D8 DF AF 7B 98 1B C9 C5 A8 41 DD 9E FB 1A 51 FE .........A....Q. 00D0: 8A 72 09 51 D3 45 BE EA 17 36 FD 37 45 59 24 6F .r.Q.E...6.7EY$o 00E0: AA EB E3 4C 65 04 15 24 30 1C 7C F0 8E F1 24 36 ...Le..$0.....$6 00F0: EE 60 B4 30 EB CD A7 21 3A 3A B5 B3 CF 8E E4 81 .`.0...!::...... public key = Sun RSA public key, 2048 bits modulus: 22540549868269337731049045024507385260542573787628838370500488975031456915675928339191598608788978166412886818018144053254194317256993635868534742497106051883418262409480683986537120518762380588035635893822782045653063382717204771221158285234168172584993231255251797413350283828305540028023358503599723497159109886144323832651476034904177315494543160791317342173062905173635050774176310860122833148864737280742410768403748999912660341255531672554245341045495023594325494277633017114644620320127314817425829498919103113286133067466723376087306471415425209209026944245886309051331485179319181933688283658147367854481639 private key = sun.security.rsa.RSAPrivateCrtKeyImpl@ffd98003
5.2 讀取test.cer文件
import java.io.FileInputStream; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; public static void main(String[] args) { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); FileInputStream fileInputStream = new FileInputStream("C:\\Users\\admin\\Desktop\\新建文件夾\\test.cer"); X509Certificate cer = (X509Certificate)certificateFactory.generateCertificate(fileInputStream); System.out.println("讀取Cer證書信息..."); System.out.println("cer_序列號___:"+cer.getSerialNumber()); System.out.println("cer_發(fā)布方標(biāo)識名___:"+cer.getIssuerDN().getName()); System.out.println("cer_主體標(biāo)識___:"+cer.getSubjectDN()); System.out.println("cer_證書算法OID字符串___:"+cer.getSigAlgOID()); System.out.println("cer_證書有效期___:" + cer.getNotBefore() + "~" + cer.getNotAfter()); System.out.println("cer_簽名算法___:"+cer.getSigAlgName()); System.out.println("cer_版本號___:"+cer.getVersion()); System.out.println("cer_公鑰___:"+cer.getPublicKey());
輸出結(jié)果展示,如下所示:
cer_發(fā)布方標(biāo)識名___:EMAILADDRESS=sky@sky.com, CN=localhost, O=sky, L=guangzhou, ST=GuangDong, C=CN cer_主體標(biāo)識___:EMAILADDRESS=test@test.com, CN=www.test.com, O=sky, ST=GuangDong, C=CN cer_證書算法OID字符串___:1.2.840.113549.1.1.11 cer_證書有效期___:Tue Aug 28 19:59:47 CST 2018~Wed Aug 28 19:59:47 CST 2019 cer_簽名算法___:SHA256withRSA cer_公鑰___:Sun RSA public key, 2048 bits modulus: 22540549868269337731049045024507385260542573787628838370500488975031456915675928339191598608788978166412886818018144053254194317256993635868534742497106051883418262409480683986537120518762380588035635893822782045653063382717204771221158285234168172584993231255251797413350283828305540028023358503599723497159109886144323832651476034904177315494543160791317342173062905173635050774176310860122833148864737280742410768403748999912660341255531672554245341045495023594325494277633017114644620320127314817425829498919103113286133067466723376087306471415425209209026944245886309051331485179319181933688283658147367854481639
讀取證書信息成功,測試完成,收工!
|