1. 程式人生 > >ssl/https配置與實現

ssl/https配置與實現

SSL協議使用不對稱加密技術實現會話雙方之間資訊的安全傳遞。可以實現資訊傳遞的保密性、完整性,並且會話雙方能鑑別對方身份。不同於常用的http協議,我們在與網站建立SSL安全連線時使用https協議,即採用的方式來訪問。
當我們與一個網站建立https連線時,我們的瀏覽器與Web Server之間要經過一個握手的過程來完成身份鑑定與金鑰交換,從而建立安全連線。具體過程如下: 
1. 使用者瀏覽器將其SSL版本號、加密設定引數、與session有關的資料以及其它一些必要資訊傳送到伺服器。 
2. 伺服器將其SSL版本號、加密設定引數、與session有關的資料以及其它一些必要資訊傳送給瀏覽器,同時發給瀏覽器的還有伺服器的證書。如果配置伺服器的SSL需要驗證使用者身份,還要發出請求要求瀏覽器提供使用者證書。 
3. 客戶端檢查伺服器證書,如果檢查失敗,提示不能建立SSL連線。如果成功,那麼繼續。 
4. 客戶端瀏覽器為本次會話生成pre-master secret,並將其用伺服器公鑰加密後傳送給伺服器。 
5. 如果伺服器要求鑑別客戶身份,客戶端還要再對另外一些資料簽名後並將其與客戶端證書一起傳送給伺服器。 
6. 如果伺服器要求鑑別客戶身份,則檢查簽署客戶證書的CA是否可信。如果不在信任列表中,結束本次會話。如果檢查通過,伺服器用自己的私鑰解密收到的pre-master secret,並用它通過某些演算法生成本次會話的master secret。 
7. 客戶端與伺服器均使用此master secret生成本次會話的會話金鑰(對稱金鑰)。在雙方SSL握手結束後傳遞任何訊息均使用此會話金鑰。這樣做的主要原因是對稱加密比非對稱加密的運算量低一個數量級以上,能夠顯著提高雙方會話時的運算速度。 
8. 客戶端通知伺服器此後傳送的訊息都使用這個會話金鑰進行加密。並通知伺服器客戶端已經完成本次SSL握手。 
9. 伺服器通知客戶端此後傳送的訊息都使用這個會話金鑰進行加密。並通知客戶端伺服器已經完成本次SSL握手。 
10. 本次握手過程結束,會話已經建立。雙方使用同一個會話金鑰分別對傳送以及接受的資訊進行加、解密。


tomcat實現SSL配置
第一步 生成KeyStore


keytool -genkey -alias tomcat -keyalg RSA –keysize 1024 –validity 730 -keystore D:\server.keystore


輸入keystore密碼: ************ [Unknown]: localhost [Unknown]: dept [Unknown]: Inc [Unknown]: bj [Unknown]: bj [Unknown]: CN
CN=localhost, OU= dept, O= Inc, L=bj, ST=bj, C=CN 正確嗎?
[否]: Y
Ychangeit (回車)


注意: localhost,是網站的域名或者ip,根據實際情況填寫,比如 192.168.0.85 否則會出現證書上的名稱無效,或者與站點名稱不匹配。


建議:將生成的 server.keystore檔案,放到%TOMCAT_HOME%或其子目錄中(如:%TOMCAT_HOME%/conf)


(其實放哪裡都一樣,只是放到%TOMCAT_HOME%裡面會方便一些)


第二步 修改server.xml


修改%TOMCAT_HOME%/conf/server.xml


去掉下面SSL HTTP那個註釋,修改為如下:


<Connector port="8443" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" 
     SSLEnabled="true"
     maxThreads="150"  
     scheme="https"  
     secure="true"  
     clientAuth="false"  
     sslProtocol="TLS"    
     keystoreFile="/conf/server.keystore"  
     keystorePass="changeit" 
/>  
keystoreFile 是server.keystore放置的位置,keystorePass是密碼 (預設密碼是changeit)


第三步


重啟Tomcat,訪問地址


(附錄:)tomcat的配置檔案SSL部分詳細說明
配置檔案server.xml,SSL部分: <!-- A "Connector" represents an endpoint by which requests are received 
        Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)   
        Java AJP   Connector: /docs/config/ajp.html 
        APR (HTTP/AJP) Connector: /docs/apr.html   
        Define a non-SSL HTTP/1.1 Connector on port 8080  
>  
<Connector  port="8443" maxHttpHeaderSize="8192"  
        maxThreads="150"  
        minSpareThreads="25"  
        maxSpareThreads="75" 
        enableLookups="false"  
        disableUploadTimeout="true" 
        acceptCount="100"  
        scheme="https"  
        secure="true"  
        clientAuth="false"  
        sslProtocol="TLS"  
        keystoreFile="D:/Tomcat/conf/tomcatKey.keystore"  
        keystorePass="changeit"  
        algorithm="SunX509"  
/>  
屬性說明: port:這個port屬性(預設值是8443)是 TCP/IP埠數碼,Tomcat在其上監聽安全連線。你可以把它更改成任何你願意要的數值(如預設的https通訊,數目是443)。不過,在許多作業系統中,要想在比1024小的埠數碼上執行Tomcat,需要特殊的設定(它超出了這個文件資料的範圍)。 redirectPort: 如果你在這裡更改埠數值,你還必須更改在non-SSL聯結器上的redirectPort 這個屬性特定的值。這允許Tomcat自動地redirect那些試圖訪問有安全限制頁面的使用者,指明根據 Servlet 2.4 Specification要求,SSL是必需的 clientAuth: 如果你想要Tomcat要求所有的SSL客戶在使用這個socket時出示使用者認證書,把這個值設定為 true 。如果你想要Tomcat要求出示使用者認證書,但是如果沒有認證書也可以, 就把這個值設定為want 。 keystoreFile: 如果你產生的keystore檔案不在Tomcat期望的預設地方(一個叫做.keystore 的檔案在Tomcat執行的主目錄),就新增這個屬性。你可以指定一個絕對路徑名稱, 或者一個由$CATALINA_BASE環境變數而派生的相對路徑名稱。 keystorePass: 如果你使用一個不同的keystore(以及認證書)密碼,而不是Tomcat期望的密碼 (就是changeit),新增這個元素。 keystoreType: 如果使用一個PKCS12 keystore的話,就新增這個element。 有效的值是JKS 和 PKCS12 sslProtocol: 要在這個socket上被使用的加密/解密協定。如果你在使用Sun的JVM,我們不提倡更改 這個值。據報道,TLS協定的IBM's 1.4.1 實現與一些通用的瀏覽器不相容。 如果是這樣,就使用value SSL ciphers: 這個socket允許使用的由逗號分隔開的加密密碼列單。預設的情況下,任何可用的密碼都允許被使用。 algorithm: 可用的X509演算法。預設是Sun的實現( SunX509 )。 對於IBM JVMs,你應該使用值 IbmX509。對於其他賣主,查閱JVM文件資料來 找正確的值。 truststoreFile: 用來驗證使用者認證書的TrustStore檔案。 truststorePass: 訪問TrustStore的密碼。預設值就是keystorePass的值。 truststoreType: 如果你在使用與KeyStore不同格式的TrustStore,新增這個元素。 合法的值是JKS和PKCS12 keyAlias: 如果 keystore 裡面有多個 key,你可以為用這個選項為加入的 key 起一個名字。 如果沒有指定名字,使用時 keystore 內的第一個 key 將會被使用。


此前我一直對https/ssl如何保護資料不被竊聽有點疑問,因為伺服器的證書是公開的,只能實行上行方向的資料加密,下行資料的加密我一直認為是瀏覽器會自動生成一個客戶端的金鑰對並將公鑰發給伺服器。仔細研究了https/ssl後發現其實並不像我想的那樣,這裡面既有非對稱加密,又因為效能原因使用了對稱加密。


基本的加解密演算法型別也就這兩種:


對稱加密 :金鑰只有一個,加密解密為同一個密碼,且加解密速度快,典型的對稱加密演算法有DES、AES等;


非對稱加密 :金鑰成對出現(且根據公鑰無法推知私鑰,根據私鑰也無法推知公鑰),加密解密使用不同金鑰(公鑰加密需要私鑰解密,私鑰加密需要公鑰解密),相對對稱加密速度較慢,典型的非對稱加密演算法有RSA、DSA等。


明白了這兩種加密型別,具體的認證過程就容易理解了:


客戶端瀏覽器連線到https/ssl伺服器,併發送ssl版本號等資訊到伺服器,協商此次連線使用的版本和引數。


伺服器根據客戶端發來的協商資料和自身支援的特性返回客戶端協商引數,並且將伺服器的證書傳送給客戶端,伺服器的證書裡包括用於非對稱加密的伺服器的公鑰。


客戶端收到伺服器的證書,可以用於鑑別伺服器身份,防止假冒的伺服器。但最重要的用處是將一段由客戶端瀏覽器隨機生成的資料pre-master secret用伺服器證書裡的公鑰進行加密,發給伺服器。注意,因為這段加密的資料只由用伺服器的私鑰才能解密,所以pre-master secret不會被人監聽到。


伺服器收到加密後的pre-master secret資料後,用自己的私鑰解密得到原始的pre-master secret,並使用一定演算法得到對稱加密的金鑰master secret。


客戶端也根據同樣的演算法得到master secret。


至此,客戶端和伺服器之間的上/下行資料傳送使用對稱加/解密,初始金鑰為master secret。常用的對稱加密演算法有RC4,AES等。


經過這些步驟就可以保證https/ssl上下行資料不被監聽並且加/解密速度也可以接受。


1. 生成證書


  這裡用到的檔案,我們存放在D:/SSL/資料夾內,其中D:/SSL/server/內的檔案是要交給伺服器用的,D:/SSL/client/內的檔案是要交給客戶端用的。


  1.1生成服務端證書


開始-執行-CMD-在dos視窗執行下執行命令:


keytool -genkey -v -alias tomcat -keyalg RSA -keystore D:/SSL/server/tomcat.keystore -dname "CN=127.0.0.1,OU=zlj,O=zlj,L=Peking,ST=Peking,C=CN" -validity 3650 -storepass zljzlj -keypass zljzlj


說明:


keytool 是JDK提供的證書生成工具,所有引數的用法參見keytool –help


-genkey 建立新證書


-v 詳細資訊


-alias tomcat 以”tomcat”作為該證書的別名。這裡可以根據需要修改


-keyalg RSA 指定演算法


-keystore D:/SSL/server/tomcat.keystore 儲存路徑及檔名


-dname "CN=127.0.0.1,OU=zlj,O=zlj,L=Peking,ST=Peking,C=CN" 證書發行者身份,這裡的CN要與釋出後的訪問域名一致。但由於我們是自己發行的證書,如果在瀏覽器訪問,仍然會有警告提示。


-validity 3650證書有效期,單位為天


-storepass zljzlj 證書的存取密碼


-keypass zljzlj 證書的私鑰


    1.2 生成客戶端證書 


    執行命令:
keytool ‐genkey ‐v ‐alias client ‐keyalg RSA ‐storetype PKCS12 ‐keystore D:/SSL/client/client.p12 ‐dname "CN=client,OU=zlj,O=zlj,L=bj,ST=bj,C=CN" ‐validity 3650 ‐storepass client ‐keypass client 


說明:
    引數說明同上。這裡的-dname 證書發行者身份可以和前面不同,到目前為止,這2個證書可以沒有任何關係。下面要做的工作才是建立2者之間的信任關係。


    1.3 匯出客戶端證書 
    執行命令:
keytool ‐export ‐alias client ‐keystore D:/SSL/client/client.p12 ‐storetype PKCS12 ‐storepass client ‐rfc ‐file D:/SSL/client/client.cer 


說明:


-export 執行匯出


-file 匯出檔案的檔案路徑


    1.4 把客戶端證書加入服務端證書信任列表 


    執行命令:
keytool ‐import ‐alias client ‐v ‐file D:/SSL/client/client.cer ‐keystore D:/SSL/server/tomcat.keystore ‐storepass zljzl 


說明:


引數說明同前。這裡提供的密碼是服務端證書的存取密碼。


    1.5 匯出服務端證書 


    執行命令:
keytool -export -alias tomcat -keystore D:/SSL/server/tomcat.keystore -storepass zljzlj -rfc -file D:/SSL/server/tomcat.cer 
  
說明:
把服務端證書匯出。這裡提供的密碼也是服務端證書的密碼。


    1.6 生成客戶端信任列表 


    執行命令:
keytool -import -file D:/SSL/server/tomcat.cer -storepass zljzlj -keystore D:/SSL/client/client.truststore -alias tomcat –noprompt


說明:
讓客戶端信任服務端證書


2. 配置服務端為只允許HTTPS連線


    2.1 配置Tomcat 目錄下的/conf/server.xml 


Xml程式碼  
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"     
   maxThreads="150" scheme="https" secure="true" clientAuth="true"     
   sslProtocol="TLS" keystoreFile="D:/SSL/server/tomcat.keystore"     
   keystorePass="zljzlj" truststoreFile="D:/SSL/server/tomcat.keystore"     
   truststorePass="zljzlj" />   


<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"  
   maxThreads="150" scheme="https" secure="true" clientAuth="true"  
   sslProtocol="TLS" keystoreFile="D:/SSL/server/tomcat.keystore"  
   keystorePass="zljzlj" truststoreFile="D:/SSL/server/tomcat.keystore"  
   truststorePass="zljzlj" />  
說明:
在server.xml裡面這段內容本來是被註釋掉的,如果想使用https的預設埠443,請修改這裡的port引數。其中的clientAuth="true" 指定了雙向證書認證。


    2.2 配置服務端專案web.xml 
    在<welcome-file-list>之後增加:
Xml程式碼  
<security-constraint>     
   <web-resource-collection>     
     <web-resource-name>services</web-resource-name>     
     <url-pattern>/services/*</url-pattern>     
   </web-resource-collection>     
   <user-data-constraint>     
     <transport-guarantee>CONFIDENTIAL</transport-guarantee>     
   </user-data-constraint>     
</security-constraint>    


<security-constraint>  
   <web-resource-collection>  
     <web-resource-name>services</web-resource-name>  
     <url-pattern>/services/*</url-pattern>  
   </web-resource-collection>  
   <user-data-constraint>  
     <transport-guarantee>CONFIDENTIAL</transport-guarantee>  
   </user-data-constraint>  
</security-constraint>   
說明:
這裡限制了WEB service服務地址的訪問必須為https連線。<url-pattern>要根據你的web service服務地址配置。


3. 修改客戶端程式碼 
在執行訪問之前,增加:
Java程式碼  
System.setProperty("javax.net.ssl.trustStore", "D:/SSL/client/client.truststore");     
System.setProperty("javax.net.ssl.trustStorePassword","zljzlj");     
System.setProperty("javax.net.ssl.keyStoreType","PKCS12") ;     
System.setProperty("javax.net.ssl.keyStore","D:/SSL/client/client.p12") ;     
System.setProperty("javax.net.ssl.keyStorePassword","client") ;     
     
String endPoint="https://127.0.0.1:8443/easbCut/services/ApplyFormService";     
...    


System.setProperty("javax.net.ssl.trustStore", "D:/SSL/client/client.truststore");  
System.setProperty("javax.net.ssl.trustStorePassword","zljzlj");  
System.setProperty("javax.net.ssl.keyStoreType","PKCS12") ;  
System.setProperty("javax.net.ssl.keyStore","D:/SSL/client/client.p12") ;  
System.setProperty("javax.net.ssl.keyStorePassword","client") ;  
  
String endPoint="https://127.0.0.1:8443/easbCut/services/ApplyFormService";  
...   通過設定引數來指定客戶端連線時所使用的客戶端證書,這裡還可以採用修改JVM啟動引數的的方式來執行,但出於不影響其他功能的考慮,這裡採用System.setProperty的方式來設定這些引數,在使用結束後,可以還原這些引數配置。


做為客戶端的開發者,可以把拿到的證書檔案後,只執行步驟3。