TLS、SSL、HTTPS以及證書

 

轉自:http://www.cnblogs.com/kyrios/p/tls-and-certificates.htmlhtml

最近在研究基於ssl的傳輸加密,涉及到了key和證書相關的話題,走了很多彎路,如今總結一下作個備忘java

科普:TLS、SSL、HTTPS以及證書

很多人可能聽過其中的超過3個名詞,但它們究竟有什麼關聯呢?node

  • TLS是傳輸層安全協議(Transport Layer Security)的縮寫,是一種對基於網絡的傳輸的加密協議,能夠在受信任的第三方公證基礎上作雙方的身份認證。TLS能夠用在TCP上,也能夠用在無鏈接的UDP報文上。協議規定了身份認證、算法協商、密鑰交換等的實現。
  • SSL是TLS的前身,如今已再也不更新
  • HTTPS是在基於TLS/SSL的安全套接字上的的應用層協議,除了傳輸層進行了加密外,其它與常規HTTP協議基本保持一致
  • 證書是TLS協議中用來對身份進行驗證的機制,是一種數字簽名形式的文件,包含證書擁有者的公鑰及第三方的證書信息。

證書分爲2類:自簽名證書和CA證書。通常自簽名證書不能用來進行身份認證,若是一個server端使用自簽名證書,client端要麼被設置爲無條件信任任何證書,要麼須要將自簽名證書的公鑰和私鑰加入受信任列表。但這樣一來就增長了server的私鑰泄露風險。linux

TLS基於CA的身份認證基本原理是:首先驗證方須要信任CA提供方本身的證書(CAcert),好比證書在操做系統的受信任證書列表中,或者用戶經過「安裝根證書」等方式將 CA的公鑰和私鑰加入受信任列表;而後CA對被驗證方的原始證書進行簽名(私鑰加密),生成最終的證書;驗證方獲得最終的證書後,利用CAcert中包含的公鑰進行解密,獲得被驗證方的原始證書。android

根據RSA的加密原理,若是用CA的公鑰解密成功,說明該證書的確是用CA的私鑰加密的,能夠認爲被驗證方是可信的。ios

下面咱們以客戶端單方對服務器端進行身份認證場景,來說解如何作證書的生成。nginx

證書的生成

證書的生成能夠用linux的OpenSSL工具鏈。對於一個網站,首先必須有本身的私鑰,私鑰的生成方式爲:算法

openssl genrsa -out ssl.key 2048

私鑰必須妥善保管,既不能丟失,也不能泄露。若是發生丟失和泄露,必須立刻從新生成,以使舊的證書失效。tomcat

若是要對私鑰進行傳輸/備份,建議先對私鑰進行密碼加密:安全

openssl rsa -in ssl.key -des3 -out encrypted.key

利用私鑰就能夠生成證書了。OpenSSL使用x509命令生成證書。這裏須要區分兩個概念:證書(certificate)和證書請求(certificate sign request)

  • 證書是自簽名或CA簽名過的憑據,用來進行身份認證
  • 證書請求是對簽名的請求,須要使用私鑰進行簽名

x509命令能夠將證書和證書請求相互轉換,不過咱們這裏只用到從證書請求到證書的過程

從私鑰或已加密的私鑰都可以生成證書請求。生成證書請求的方法爲:

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

若是私鑰已加密,須要輸入密碼。req命令會經過命令行要求用戶輸入國家、地區、組織等信息,這些信息會附加在證書中展現給鏈接方。

接下來用私鑰對證書請求進行簽名。根據不一樣的場景,簽名的方式也略有不一樣

自簽名,生成私有證書

自簽名的原理是用私鑰對該私鑰生成的證書請求進行簽名,生成證書文件。該證書的簽發者就是本身,因此驗證方必須有該證書的私鑰才能對簽發信息進行驗證,因此要麼驗證方信任一切證書,面臨冒名頂替的風險,要麼被驗證方的私鑰(或加密過的私鑰)須要發送到驗證方手中,面臨私鑰泄露的風險。

固然自簽名也不是一無用處,好比須要內部通信的兩臺電腦須要使用加密又不想用第三方證書,能夠在兩端使用相同的私鑰和證書進行驗證(固然這樣就跟對稱加密沒有區別了)

自簽名的方法爲:

openssl x509 -req -in ssl.csr -signkey ssl.key -out ssl.crt

一樣若是ssl.key已加密,須要輸入密碼。

自簽名,生成CA證書

CA證書是一種特殊的自簽名證書,能夠用來對其它證書進行簽名。這樣當驗證方選擇信任了CA證書,被簽名的其它證書就被信任了。在驗證方進行驗證時,CA證書來自操做系統的信任證書庫,或者指定的證書列表。

生成自簽名證書的方法爲:

openssl x509 -req -in sign.csr -extensions v3_ca -signkey sign.key -out sign.crt

利用CA證書進行簽名

使用CA證書對其它證書進行簽名的方法爲:

openssl x509 -req -in ssl.csr -extensions v3_usr -CA sign.crt -CAkey sign.key -CAcreateserial -out ssl.crt

花錢購買證書機構的簽名

利用上述方法,受信任的機構就能夠用本身的私鑰(sign.key)對其餘人的證書進行簽名。咱們看到,只須要把證書請求(ssl.csr)發給證書機構,證書機構就能夠生成出簽名過的證書(ssl.crt)。目前購買證書籤名服務的價格大約爲100-400元/年。

可選的證書機構有:godaddy startssl namecheap

證書/私鑰格式

openssl默認使用PEM格式(形如-----BEGIN CERTIFICATE----- ... ... -----END CERTIFICATE---)存放證書和私鑰,nginx/node.js可使用該格式啓動服務。

但使用tomcat或java客戶端/android時,不能使用該格式的證書。jdk中包含了一個keytool命令,能夠完成整個的證書生成過程,不過這裏咱們只用openssl工具也能夠完成java的支持,即便用PKCS12格式對證書進行打包。

PKCS12格式文件,能夠包含多個證書/私鑰對,指定多個受信任的server(也能夠不包含證書),每一個server有一個alias name。咱們來看最簡單的只包含一個alias的文件生成:

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

上面的命令將CA證書及其私鑰導出爲sign.p12文件,導出時須要指定一個密碼。

 

java客戶端程序中對p12文件進行信任

若是咱們的服務器使用了本身建立的CA證書籤名的證書,或者使用了自簽名證書,客戶端在使用ssl時,須要將導出的證書文件加入到信任列表中。下面是一段導入證書的示例代碼:

複製代碼
 1 javax.net.SocketFactory initSSLSocketFactory(InputStream keyin, char[] password) throws Exception {
 2         java.security.KeyStore keyStore = java.security.KeyStore.getInstance("PKCS12");
 3         keyStore.load(keyin, password);
 4         keyin.close();
 5 
 6         javax.net.ssl.TrustManagerFactory trustManagerFactory = javax.net.ssl.TrustManagerFactory.getInstance(javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm());
 7         trustManagerFactory.init(keyStore);
 8 
 9         javax.net.ssl.SSLContext sslContext = javax.net.ssl.SSLContext.getInstance("SSL");
10 
11         sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
12 
13         return sslContext.getSocketFactory();
14 }
複製代碼

咱們獲得了一個SocketFactory,能夠用它來初始化ssl/https鏈接。

相關文章
相關標籤/搜索