加密之SSL和單雙向認證


1 SSL

1.1 SSL了解

SSL配置是我們在實際應用中經常見到的場景
SSL(Secure Sockets Layer,安全套接層)是為通信提供安全及數據完整性的一種安全協議,SSL在網絡傳送層對網絡連接進行加密。SSL協議位於TCP/IP協議與各種應用層協議之間,為數據通信提供安全支持。
SSL協議可分為兩層:

  • SSL記錄協議(SSL Record Rrotocol),它建立在可靠的傳輸協議(如TCP)之上,為高層協議提供數據封裝、壓縮、加密等基本功能的支持
  • SSL握手協議(SSL Handshake Protocol),它建立在SSL記錄協議之上,用於在實際數據傳輸開始前,通信雙方進行身份認證、協商加密算法、交互加密密鑰等

1.2 導入證書

我們需要構建一個由CA機構簽發的有效證書,這里我們先生成的自簽名證書zlex.cer(具體生產證書密鑰步驟點此了解)
這里,我們將證書導入到我們的密鑰庫。

keytool -import -alias www.zlex.org -file d:/zlex.cer -keystore d:/zlex.keystore  

其中:

  • import:表示導入
  • alias:指定別名,這里是www.zlex.org
  • file:指輸入文件名,這里是d:/zlex.cer
  • keystore:指定存儲位置,這里是d:/zlex.keystore

在這里我使用的密碼為654321

控制台輸出:

輸入keystore密碼:  
再次輸入新密碼:  
所有者:CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN  
簽發人:CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN  
序列號:4a1e48df  
有效期: Thu May 28 16:18:39 CST 2009 至Wed Aug 26 16:18:39 CST 2009  
證書指紋:  
         MD5:19:CA:E6:36:E2:DF:AD:96:31:97:2F:A9:AD:FC:37:6A  
         SHA1:49:88:30:59:29:45:F1:69:CA:97:A9:6D:8A:CF:08:D2:C3:D5:C0:C4  
         簽名算法名稱:SHA1withRSA  
         版本: 3  
信任這個認證? [否]:  y  
認證已添加至keystore中  

1.3 tomcat配置SSL

接下來我們將域名www.zlex.org定位到本機上。打開C:\Windows\System32\drivers\etc\hosts文件,將www.zlex.org綁定在本機上。在文件末尾追加127.0.0.1 www.zlex.org
現在通過地址欄訪問http://www.zlex.org,或者通過ping命令,如果能夠定位到本機,域名映射就搞定了。
現在,配置tomcat。先將zlex.keystore拷貝到tomcatconf目錄下,然后配置server.xml。將如下內容加入配置文件

<Connector  
    SSLEnabled="true"  
    URIEncoding="UTF-8"  
    clientAuth="false"  
    keystoreFile="conf/zlex.keystore"  
    keystorePass="123456"  
    maxThreads="150"  
    port="443"  
    protocol="HTTP/1.1"  
    scheme="https"  
    secure="true"  
    sslProtocol="TLS" />  

注意clientAuth="false"測試階段,置為false,正式使用時建議使用true。現在啟動tomcat,就可以訪問https://www.zlex.org/進行測試

顯然,證書未能通過認證,這個時候你可以選擇安裝證書(上文中的zlex.cer文件就是證書),作為受信任的根證書頒發機構導入,再次重啟瀏覽器,訪問https://www.zlex.org/,就會看到地址欄中會有個小鎖
,就說明安裝成功。所有的瀏覽器聯網操作已經在RSA加密解密系統的保護之下了。但似乎我們感受不到。
這個時候很多人開始懷疑,如果我們要手工做一個這樣的https的訪問是不是需要把瀏覽器的這些個功能都實現呢?不需要!

點擊了解Spring Boot配置SSL過程

1.4 具體操作

點擊此處了解 獲取公私鑰,加密解密,加簽驗簽,驗證證書有效期

configSSLSocketFactory方法供外界調用,該方法為HttpsURLConnection配置了SSLSocketFactory。當HttpsURLConnection配置了SSLSocketFactory后,就可以通過HttpsURLConnectiongetInputStreamgetOutputStream,像往常使用HttpURLConnection做操作了。尤其要說明一點,未配置SSLSocketFactory前,HttpsURLConnectiongetContentLength()獲得值永遠都是-1

/**
* 獲得SSL SocektFactory
*/
private static SSLSocketFactory getSSLSocketFactory(String password,String keyStorePath, String trustKeyStorePath) throws Exception {
        // 初始化密鑰庫  
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(SunX509);

        FileInputStream is = new FileInputStream(keyStorePath);
        KeyStore keyStore = KeyStore.getInstance(KEY_STORE);
        keyStore.load(is, password.toCharArray());
        is.close();

        keyManagerFactory.init(keyStore, password.toCharArray());

        // 初始化信任庫  
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(SunX509);
        FileInputStream is_trustkeyStore = new FileInputStream(trustKeyStorePath);
        KeyStore trustkeyStore = KeyStore.getInstance(KEY_STORE);
        trustkeyStore.load(is_trustkeyStore, password.toCharArray());
        is.close();
        trustManagerFactory.init(trustkeyStore);

        // 初始化SSL上下文  
        SSLContext ctx = SSLContext.getInstance(SSL);
        ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
        SSLSocketFactory sf = ctx.getSocketFactory();

        return sf;
    }

    /**
     * 為HttpsURLConnection配置SSLSocketFactory
     */
    public static void configSSLSocketFactory(HttpsURLConnection conn, String password, String keyStorePath, String trustKeyStorePath)throws Exception {
        conn.setSSLSocketFactory(getSSLSocketFactory(password, keyStorePath,trustKeyStorePath));
    }

驗證結果

private static String clientKeyStorePath = "d:/zlex-client.keystore";
    private static String clientPassword = "654321";

    public static void main(String[] args) throws Exception {
        URL url = new URL("https://www.zlex.org/examples/");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

        conn.setDoInput(true);
        conn.setDoOutput(true);

        configSSLSocketFactory(conn, clientPassword, clientKeyStorePath, clientKeyStorePath);

        InputStream is = conn.getInputStream();
        int length = conn.getContentLength();

        DataInputStream dis = new DataInputStream(is);
        byte[] data = new byte[length];
        dis.readFully(data);

        dis.close();
        System.err.println(new String(data));
        conn.disconnect();
    }

2 單向認證

2.1 第三方簽名

在上面我們使用自簽名證書完成了認證。接下來,我們使用第三方CA簽名機構完成證書簽名。
這里我們使用thawte提供的測試用21天免費ca證書。

  1. 要在該網站上注明你的域名,這里使用www.test.org作為測試用域名
  2. 如果域名有效,你會收到郵件要求你訪問https://www.thawte.com/cgi/server/try.exe獲得ca證書。
  3. 復述密鑰庫的創建。
keytool -genkey -validity 36000 -alias www.test.org -keyalg RSA -keystore d:\zlex.keystore  

在這里使用的密碼為 123456

控制台輸出:

密碼:  
再次輸入新密碼:  
您的名字與姓氏是什么?  
  [Unknown]:  www.zlex.org  
您的組織單位名稱是什么?  
  [Unknown]:  zlex  
您的組織名稱是什么?  
  [Unknown]:  zlex  
您所在的城市或區域名稱是什么?  
  [Unknown]:  BJ  
您所在的州或省份名稱是什么?  
  [Unknown]:  BJ  
該單位的兩字母國家代碼是什么  
  [Unknown]:  CN  
CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN 正確嗎?  
  [否]:  Y  
  
輸入<tomcat>的主密碼  
        (如果和 keystore 密碼相同,按回車):  
再次輸入新密碼:  
  1. 通過如下命令,從zlex.keystore中導出CA證書申請。
keytool -certreq -alias www.test.org -file d:\zlex.csr -keystore d:\zlex.keystore -v 

就會獲得zlex.csr文件,可以用記事本打開,內容如下格式:

-----BEGIN NEW CERTIFICATE REQUEST-----  
MIIBnDCCAQUCAQAwXDELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAkJKMQswCQYDVQQHEwJCSjENMAsG  
A1UEChMEemxleDENMAsGA1UECxMEemxleDEVMBMGA1UEAxMMd3d3LnpsZXgub3JnMIGfMA0GCSqG  
SIb3DQEBAQUAA4GNADCBiQKBgQCR6DXU9Mp+mCKO7cv9JPsj0n1Ec/GpM09qvhpgX3FNad/ZWSDc  
vU77YXZSoF9hQp3w1LC+eeKgd2MlVpXTvbVwBNVd2HiQPp37ic6BUUjSaX8LHtCl7l0BIEye9qQ2  
j8G0kak7e8ZA0s7nb3Ymq/K8BV7v0MQIdhIc1bifK9ZDewIDAQABoAAwDQYJKoZIhvcNAQEFBQAD  
gYEAMA1r2fbZPtNx37U9TRwadCH2TZZecwKJS/hskNm6ryPKIAp9APWwAyj8WJHRBz5SpZM4zmYO  
oMCI8BcnY2A4JP+R7/SwXTdH/xcg7NVghd9A2SCgqMpF7KMfc5dE3iygdiPu+UhY200Dvpjx8gmJ  
1UbH3+nqMUyCrZgURFslOUY=  
-----END NEW CERTIFICATE REQUEST-----  
  1. 將上述文件內容拷貝到https://www.thawte.com/cgi/server/try.exe中,點擊next,獲得回應內容,這里是p7b格式。
    內容如下:
-----BEGIN PKCS7-----  
MIIF3AYJKoZIhvcNAQcCoIIFzTCCBckCAQExADALBgkqhkiG9w0BBwGgggWxMIID  
EDCCAnmgAwIBAgIQA/mx/pKoaB+KGX2hveFU9zANBgkqhkiG9w0BAQUFADCBhzEL  
MAkGA1UEBhMCWkExIjAgBgNVBAgTGUZPUiBURVNUSU5HIFBVUlBPU0VTIE9OTFkx  
HTAbBgNVBAoTFFRoYXd0ZSBDZXJ0aWZpY2F0aW9uMRcwFQYDVQQLEw5URVNUIFRF  
U1QgVEVTVDEcMBoGA1UEAxMTVGhhd3RlIFRlc3QgQ0EgUm9vdDAeFw0wOTA1Mjgw  
MDIxMzlaFw0wOTA2MTgwMDIxMzlaMFwxCzAJBgNVBAYTAkNOMQswCQYDVQQIEwJC  
SjELMAkGA1UEBxMCQkoxDTALBgNVBAoTBHpsZXgxDTALBgNVBAsTBHpsZXgxFTAT  
BgNVBAMTDHd3dy56bGV4Lm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA  
keg11PTKfpgiju3L/ST7I9J9RHPxqTNPar4aYF9xTWnf2Vkg3L1O+2F2UqBfYUKd  
8NSwvnnioHdjJVaV0721cATVXdh4kD6d+4nOgVFI0ml/Cx7Qpe5dASBMnvakNo/B  
tJGpO3vGQNLO5292JqvyvAVe79DECHYSHNW4nyvWQ3sCAwEAAaOBpjCBozAMBgNV  
HRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBABgNVHR8E  
OTA3MDWgM6Axhi9odHRwOi8vY3JsLnRoYXd0ZS5jb20vVGhhd3RlUHJlbWl1bVNl  
cnZlckNBLmNybDAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9v  
Y3NwLnRoYXd0ZS5jb20wDQYJKoZIhvcNAQEFBQADgYEATPuxZbtJJSPmXvfrr1yz  
xqM06IwTZ6UU0lZRG7I0WufMjNMKdpn8hklUhE17mxAhGSpewLVVeLR7uzBLFkuC  
X7wMXxhoYdJZtNai72izU6Rd1oknao7diahvRxPK4IuQ7y2oZ511/4T4vgY6iRAj  
q4q76HhPJrVRL/sduaiu+gYwggKZMIICAqADAgECAgEAMA0GCSqGSIb3DQEBBAUA  
MIGHMQswCQYDVQQGEwJaQTEiMCAGA1UECBMZRk9SIFRFU1RJTkcgUFVSUE9TRVMg  
T05MWTEdMBsGA1UEChMUVGhhd3RlIENlcnRpZmljYXRpb24xFzAVBgNVBAsTDlRF  
U1QgVEVTVCBURVNUMRwwGgYDVQQDExNUaGF3dGUgVGVzdCBDQSBSb290MB4XDTk2  
MDgwMTAwMDAwMFoXDTIwMTIzMTIxNTk1OVowgYcxCzAJBgNVBAYTAlpBMSIwIAYD  
VQQIExlGT1IgVEVTVElORyBQVVJQT1NFUyBPTkxZMR0wGwYDVQQKExRUaGF3dGUg  
Q2VydGlmaWNhdGlvbjEXMBUGA1UECxMOVEVTVCBURVNUIFRFU1QxHDAaBgNVBAMT  
E1RoYXd0ZSBUZXN0IENBIFJvb3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB  
ALV9kG+Os6x/DOhm+tKUQfzVMWGhE95sFmEtkMMTX2Zi4n6i6BvzoReJ5njzt1LF  
cqu4EUk9Ji20egKKfmqRzmQFLP7+1niSdfJEUE7cKY40QoI99270PTrLjJeaMcCl  
+AYl+kD+RL5BtuKKU3PurYcsCsre6aTvjMcqpTJOGeSPAgMBAAGjEzARMA8GA1Ud  
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAgozj7BkD9O8si2V0v+EZ/t7E  
fz/LC8y6mD7IBUziHy5/53ymGAGLtyhXHvX+UIE6UWbHro3IqVkrmY5uC93Z2Wew  
A/6edK3KFUcUikrLeewM7gmqsiASEKx2mKRKlu12jXyNS5tXrPWRDvUKtFC1uL9a  
12rFAQS2BkIk7aU+ghYxAA==  
-----END PKCS7-----  

將其存儲為zlex.p7b
6. 將由CA簽發的證書導入密鑰庫。

keytool -import -trustcacerts -alias www.test.org -file d:\zlex.p7b -keystore d:\zlex.keystore -v  

在這里使用的密碼為 123456

控制台輸出:

輸入keystore密碼:  
  
回復中的最高級認證:  
  
所有者:CN=Thawte Test CA Root, OU=TEST TEST TEST, O=Thawte Certification, ST=FOR  
 TESTING PURPOSES ONLY, C=ZA  
簽發人:CN=Thawte Test CA Root, OU=TEST TEST TEST, O=Thawte Certification, ST=FOR  
 TESTING PURPOSES ONLY, C=ZA  
序列號:0  
有效期: Thu Aug 01 08:00:00 CST 1996 至Fri Jan 01 05:59:59 CST 2021  
證書指紋:  
         MD5:5E:E0:0E:1D:17:B7:CA:A5:7D:36:D6:02:DF:4D:26:A4  
         SHA1:39:C6:9D:27:AF:DC:EB:47:D6:33:36:6A:B2:05:F1:47:A9:B4:DA:EA  
         簽名算法名稱:MD5withRSA  
         版本: 3  
  
擴展:  
  
#1: ObjectId: 2.5.29.19 Criticality=true  
BasicConstraints:[  
  CA:true  
  PathLen:2147483647  
]  
  
  
... 是不可信的。 還是要安裝回復? [否]:  Y  
認證回復已安裝在 keystore中  
[正在存儲 d:\zlex.keystore]  
  1. 域名定位
    將域名www.test.org定位到本機上。打開C:\Windows\System32\drivers\etc\hosts文件,將www.test.org綁定在本機上。在文件末尾追加127.0.0.1 www.test.org。現在通過地址欄訪問http://www.test.org,或者通過ping命令,如果能夠定位到本機,域名映射就搞定了
  2. 配置server.xml
<Connector  
    keystoreFile="conf/zlex.keystore"  
    keystorePass="123456"   
    truststoreFile="conf/zlex.keystore"      
    truststorePass="123456"       
    SSLEnabled="true"  
    URIEncoding="UTF-8"  
    clientAuth="false"            
    maxThreads="150"  
    port="443"  
    protocol="HTTP/1.1"  
    scheme="https"  
    secure="true"  
    sslProtocol="TLS" />  

3 雙向認證

3.1 引言

對於雙向認證,做一個簡單的描述。
服務器端下發證書,客戶端接受證書。證書帶有公鑰信息,用於驗證服務器端、對數據加密/解密,起到OSI五類服務的認證(鑒別)服務和保密性服務。 這只是單向認證,為什么?
因為客戶端可以驗證服務器端,但服務器端不能驗證客戶端!
如果客戶端也有這樣一個證書,服務器端也就能夠驗證客戶端,這就是雙向認證了,換言之,當你用銀行的U盾之類的U盤與銀行賬戶交互時,在你驗證銀行服務器的同時,服務器也在驗證你!這種雙重驗證,正是網銀系統的安全關鍵!

雙向認證需要一個CA機構簽發這樣的客戶端、服務器端證書,首先需要CA機構構建一個根證書。keytool可以構建證書但不能構建我們需要的根證書,openssl則可以,根證書簽發客戶端證書,根私鑰簽發服務器端證書
直接使用linux下的openssl來完成CA,需要修改openssl.cnf文件,在ubuntu下的/etc/ssl/目錄下,找到[ CA_default ]修改dir變量。

#dir = ./demoCA # Where everything is kept 

我們把c盤的ca目錄作為CA認證的根目錄,文件修改后如下所示:

dir = $ENV::HOME/ca # Where everything is kept 

3.2 使用openssl腳本

我們需要在用戶目錄下構建一個ca目錄,以及子目錄,如下所下:
ca
|__certs
|__newcerts
|__private
|__crl

執行如下操作:

#!/bin/bash     
  
ca_path=ca  
certs_path=$ca_path/certs  
newcerts_path=$ca_path/newcerts  
private_path=$ca_path/private  
crl_path=$ca_path/crl  
  
echo 移除CA根目錄     
rm -rf ca     
    
echo 構建CA根目錄     
mkdir ca     
   
echo 構建子目錄     
mkdir certs     
mkdir newcerts     
mkdir private     
mkdir crl    
  
#構建文件     
touch $ca_path/index.txt  
echo 01 > $ca_path/serial  
echo      
  
#構建隨機數     
openssl rand -out $private_path/.rand 1000  
echo      
  
echo 生成根證書私鑰     
openssl genrsa -des3 -out $private_path/ca.pem 2048  
echo     
  
echo 查看私鑰信息  
openssl rsa -noout -text -in $private_path/ca.pem  
echo  
  
echo 生成根證書請求      
openssl req -new -key $private_path/ca.pem -out $certs_path/ca.csr -subj "/C=CN/ST=BJ/L=BJ/O=zlex/OU=zlex/CN=ca.zlex.org"  
echo     
  
echo 查看證書請求   
openssl req -in $certs_path/ca.csr -text -noout  
echo   
  
echo 簽發根證書     
openssl ca -create_serial -out $certs_path/ca.crt -days 3650 -batch -keyfile $private_path/ca.pem -selfsign -extensions v3_ca -infiles $certs_path/ca.csr   
#openssl x509 -req -sha1 -extensions v3_ca -signkey $private_path/ca.pem -in $certs_path/ca.csr -out $certs_path/ca.crt -days 3650  
echo     
  
echo 查看證書詳情  
openssl x509 -in $certs_path/ca.crt -text -noout  
echo  
  
echo 證書轉換——根證書     
openssl pkcs12 -export -clcerts -in $certs_path/ca.crt -inkey $private_path/ca.pem -out $certs_path/ca.p12  
echo    
  
echo 生成服務器端私鑰     
openssl genrsa -des3 -out $private_path/server.pem 1024  
echo     
  
echo 查看私鑰信息  
openssl rsa -noout -text -in $private_path/server.pem  
echo  
  
echo 生成服務器端證書請求     
openssl req -new -key $private_path/server.pem -out $certs_path/server.csr -subj "/C=CN/ST=BJ/L=BJ/O=zlex/OU=zlex/CN=www.zlex.org"  
echo     
  
echo 查看證書請求   
openssl req -in $certs_path/server.csr -text -noout  
echo   
  
echo 簽發服務器端證書  
openssl ca -in $certs_path/server.csr -out $certs_path/server.crt -cert $certs_path/ca.crt -keyfile $private_path/ca.pem -days 365 -notext  
#openssl x509 -req -days 365 -sha1 -extensions v3_req -CA $certs_path/ca.crt -CAkey $private_path/ca.pem -CAserial $ca_path/serial -CAcreateserial -in $certs_path/server.csr -out $certs_path/server.crt  
echo  
  
echo 查看證書詳情  
openssl x509 -in $certs_path/server.crt -text -noout  
echo  
  
echo 證書轉換——服務器端     
openssl pkcs12 -export -clcerts -in $certs_path/server.crt -inkey $private_path/server.pem -out $certs_path/server.p12  
echo      
  
echo 生成客戶端私鑰     
openssl genrsa -des3 -out $private_path/client.pem 1024  
echo     
  
echo 生成客戶端私鑰     
openssl genrsa -des3 -out $private_path/client.pem 1024  
echo     
  
echo 查看私鑰信息  
openssl rsa -noout -text -in $private_path/client.pem  
echo  
  
echo 生成客戶端證書請求     
openssl req -new -key $private_path/client.pem -out $certs_path/client.csr -subj "/C=CN/ST=BJ/L=BJ/O=zlex/OU=zlex/CN=zlex"  
echo     
  
echo 查看證書請求   
openssl req -in $certs_path/client.csr -text -noout  
echo   
  
echo 簽發客戶端證書     
openssl ca -in $certs_path/client.csr -out $certs_path/client.crt -cert $certs_path/ca.crt -keyfile $private_path/ca.pem -days 365 -notext  
#openssl x509 -req -days 365 -sha1 -extensions dir_sect -CA $certs_path/ca.crt -CAkey $private_path/ca.pem -CAserial $ca_path/serial -in $certs_path/client.csr -out $certs_path/client.crt  
echo     
  
echo 查看證書詳情  
openssl x509 -in $certs_path/client.crt -text -noout  
echo  
  
echo 證書轉換——客戶端     
openssl pkcs12 -export -clcerts -in $certs_path/client.crt -inkey $private_path/client.pem -out $certs_path/client.p12  
echo   
  
echo 生成證書鏈PKCS#7  
openssl crl2pkcs7 -nocrl -certfile $certs_path/server.crt -certfile $certs_path/ca.crt -certfile $certs_path/client.crt -out  
form PEM -out $certs_path/zlex.p7b  
echo  
  
echo 查看證書鏈  
openssl pkcs7 -in $certs_path/zlex.p7b -print_certs -noout  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM