數字證書、SSL、HTTPS及在Nginx中的配置


一、什么是 RSA、SSL、HTTPS

RSA:它是非對稱加密算法的一種,而且是最常用的一種。它的理論基礎是:計算兩個大質數的乘積非常簡單,而對該乘積進行因子分解就非常困難。而且

         這兩個質數越大,對其乘積的分解就越困難。RSA生成的密鑰對有公鑰和私鑰之分,不過,貌似密鑰對中的任何一個當公鑰都行,公鑰是可以公開的,

         私鑰只有自己知道,公鑰加密的數據只有私鑰才能解密,反之私鑰加密的數據也只有公鑰才能解密。目前,公開聲明破解的密鑰位數是768位,因此

         長度為1024的RSA密鑰是有一定危險的,建議密鑰用2048位的。量子計算機對破解RSA比較有效。

SSL:全稱是Secure Sockets Layer,是介於TCP層協議和HTTP協議之間的協議,如果用TCP/IP五層協議來考察,那SSL屬於應用層,與HTTP在同一層。

        SSL協議與HTTP協議沒任何關系,它是一個安全協議,用於對數據包(有應用層協議頭)進行加密,因此,我們也可以對FTP、SMTP等協議用SSL協議

        加密,即FTPS、SMTPS。SSL采用非對稱加密算法,比如可以選擇RSA算法。

HTTPS:它其實只是SSL協議+HTTP協議的組合而已,類似的還有FTPS、SMTPS等等。HTTPS 不同於 HTTP 的端口,HTTP默認端口為80,而HTTPS默

        認端口為443。

數字簽名:用私鑰對發送的信息的hash值進行加密,得到的加密數據就是數字簽名,我們最常見到的是CA對數字證書進行簽名。數字簽名的作用是可以檢查

         數據在傳輸過程中是否被人篡改了,因為如果篡改了,那hash值必定會變化,就與數字簽名解密后的值不一樣了,而由於篡改者沒有CA私鑰,所以沒

         法重新生成數字簽名。你可能會問,為什么不直接對信息加密,而是要對其hash值進行加密呢?從效力上講,兩者是等效的,都可以驗證信息是否被人

         篡改過。當信息量大時,直接對信息加密(以及客戶端收到信息后解密)太耗時,所以用信息的hash值。

數字證書:里面包含服務器公鑰、其它信息、還會附加服務器公鑰和證書信息的數字簽名。這里的其它信息包含頒發者、有效期、使用者common name-簡稱CN,

         簽名算法,簽名哈希算法等。一般來說,我們會使用權威CA認證頒發的數字證書,該證書中附加的數字簽名就是CA用自己的私鑰對“證書中的公鑰和

         證書信息“的hash值加密后得到的。我們可以看到,數字證書本身是沒有加密的,只是附加了一個數字簽名而已,因此,在傳輸過程中別人是可以竊聽

         的,不過沒有關系,我們在傳輸數字證書時,主要是防止別人的篡改和冒充,保證公鑰就是客戶端所訪問的服務器發來的公鑰,而沒有被人篡改,也

         沒有被冒充,關於冒充,見下面的SSL實現的功能第3點。我們可以通過檢查數字簽名來保證沒有被篡改,通過該證書的頒發者是否為權威CA以及

         common name是否為http request header中的host(不包括端口)來保證沒有被別人冒充。

       

使用SSL可以實現下面的功能:

1、數據加密傳輸,防止竊聽。SSL常用的非對稱加密算法是RSA,RSA基於的理論是:兩個大質數相乘計算非常容易,但對該乘積進行因子分解非常困難,

     而且該乘積越大,破解越難。目前公開聲明破解的密鑰位數是768,因此密鑰長度為1024的RSA是有一定危險的,建議密鑰長度用2048位。量子計算

     機對破解RSA有效,目前還不確定美國國安局NSA是否已經掌握了長密鑰RSA的破解方法。

2、可以進行數據完整性檢查,防篡改。

3、可以進行身份驗證,防冒充。比如客戶端給服務端發請求時,先要DNS查找服務器的IP,而DNS時被一個黑客攔截,返回了黑客指定的IP,該IP的服務

     給客戶端返回了一個證書,為了使客戶端驗證通過,該證書必須是權威CA機構頒發的,而且證書中的服務器域名必須與客戶端請求的域名相同,為了保

     證這兩點,那黑客要有某個權威CA頒發的該域名的證書,如果該黑客想直接在權威CA上申請該域名的證書,那是不可行的,因為CA會用一些辦法(比

     如給注冊域名時所用的郵箱發一封確認郵件)驗證該域名是否屬性黑客,顯然,黑客無法通過驗證。另一種方法是黑客直接用瀏覽器等客戶端去從服務

     端獲取,這是可以得到的。但是黑客無法獲取到服務器私鑰,這樣即使它將服務器的IP定向到自己的服務器,但客戶端發來的對稱密鑰由於是用證書中

     包含的公鑰加密的,黑客是無法解密的。

二、SSL通信過程

     這里只是一個簡化的通信過程(主要簡化了生成對稱密鑰的過程),目的只是方便理解SSL原理。

     首先,要向CA申請證書,也可以是自簽的證書。在證書請求文件中,包含服務端的公鑰,還有域名、Email、地址等信息。CA用自己的私鑰將這些信息

加密生成一個證書,該證書會注明CA名稱。我們向CA申請證書基於一個假設:即認為CA的證書是可靠的,可信的。我們可以看到,其實SSL通信過程中,

涉及到兩對非對稱密鑰和一對對稱密鑰。兩對非對稱密鑰是指CA自己的非對稱密鑰和我們服務器的非對稱密鑰,簡單說一下他們的作用,如下

      CA非對稱密鑰對的作用:簡單點說吧,CA用私鑰對證書進行加密(注:證書中包含服務器的公鑰),這樣可以做到黑客無法篡改證書中的公鑰,保證公鑰

只能是域名服務器發來的。如果不用CA私鑰加密證書,那證書傳輸過程中,黑客可以劫持並篡改證書中的公鑰為自己的公鑰,並通過DNS劫持和修改,指向自己

的服務器IP,這是非常危險的。CA的非對稱密鑰中,私鑰由CA自己保存,當用戶申請CA證書時,CA會用該私鑰對證書進行數字簽名,這樣可以保證黑客無法修

改證書,因為黑客修改證書信息后,必須重新計算hash,重新生成加密生成數字簽名,但黑客沒有CA的私鑰,所以沒法對該hash加密。在SSL通信過程中,當

客戶端收到服務器發來的證書后,先計算出該證書信息的hash,然后用CA公鑰解密證書上的數字簽名,得到hash,如果兩個hash相同,那就說明證書沒有被篡

改過。

     服務器非對稱密鑰對的作用:加密解密對稱密鑰,在SSL通信過程中,客戶端將對稱密鑰發給服務器時,要用服務器的非對稱密鑰加密的,這樣保證對稱密鑰

的傳輸安全。

 

SSL握手過程如下:

1、客戶端向服務器發請求,請求證書

2、服務器把證書發給客戶端

3、客戶端一般會有大部分CA的公鑰,客戶端收到證書后,檢查該頒發者是否是客戶端認可的CA,如果是,就用該CA的公鑰解密數字簽名,然后再計算

    證書中的”公鑰和證書信息“的hash值,比較兩者,如果相同,那就說明該證書沒有被人篡改過,而且是該CA機構頒發的。當然,還會進行其它驗證,

    如證書的common name與http request header中的host(不包括端口)是否相同,等等,如果有哪項檢查不通過,會有告警,如果所有檢查通過,

    那進入第4步。

4、客戶端生成對稱密鑰,用證書中的公鑰加密,發給服務器

5、服務器收到對稱密鑰后保存,給客戶端一個應答。

6、客戶端接收響應,這樣就完成了SSL連接,后面的通信用對稱密鑰加密數據傳輸。  

因為非對稱加密相對對稱加密來說比較耗時,所以正式的數據傳輸是用對稱加密算法。非對稱加密只是用於建立SSL時對稱密鑰的安全傳輸。我們可以設置

HTTPS長連接,這樣建立好SSL+HTTP連接后,可以用這個連接發多次HTTPS請求,而不用每次請求都建立連接。

 

三、什么網站需要使用SSL證書

這塊我還沒完全搞懂,因為很多網站在登陸時用HTTPS,而登陸后用的HTTP,我有些不解,因為登陸時用HTTPS可以防止別人截獲用戶名和

密碼,那登陸后用HTTP就不怕被人截獲cookie嗎?莫非可以使用HTTPS中的對稱密鑰對HTTP中的數據進行加密?

 

四、自簽SSL證書

需要先安裝openssl,使用openssl給服務器生成RSA密鑰及證書。如果是用權威的CA,在你申請CA證書過程中,他會幫你生成私鑰,這樣你就不需要用openssl生成了。

startssl就提供了這個功能。

# 生成一個RSA私鑰,1024是加密強度,一般是1024或2048 
$ openssl genrsa -out private.key 1024
 
# 生成一個證書請求
$ openssl req -new -key private.key -out cert_req.csr

# 自己簽發證書,如果要權威CA簽發的話,要把cert_req.csr發給CA
$ openssl x509 -req -days 365 -in cert_req.csr -signkey private.key -out server_cert.crt
 

第2個命令是生成證書請求,會提示輸入省份、城市、域名(圖中的Common Name)、Email等,這里主要是保證Common Name用網站域名,

如果沒有申請域名,客戶端直接通過服務器IP訪問,那這里就輸入服務器IP。另外,對於自簽名的證書,建議生成的私鑰不要加密。生成的

書請求文件cert_req.csr中除了包含這些手動輸入的信息外,它還包含private.key對應的公鑰,你可能會有一個疑問,根據私鑰就能生成公鑰嗎?

當然不是,如果只單純的知道私鑰,可以認為是無法計算出公鑰的,關鍵在於Putty在產生私鑰時,還會在內存中保存必要的公鑰參數。最后由該證

書生成自簽的證書,見圖1.

                                                                                    圖1
                                                                    

編輯配置文件nginx.conf,給站點加上HTTPS協議,重啟Nginx后即可通過https訪問網站了。

server {
    server_name 192.168.1.100; # 客戶端直接用IP來訪問
    # 這是默認的SSL端口,可以修改為其它端口,瀏覽器用https訪問url時,默認就是用這個端口,
    # 如果下面listen修改成其它端口,那瀏覽器用https訪問時,就要指定端口了。
    listen 443; 
    ssl on;
    ssl_certificate /home/xiaobai/server_cert.crt;
#使用無密碼私鑰 ssl_certificate_key
/usr/xiaobai/private.key; }
 

     在SSL握手的過程中,客戶端收到服務端的證書后,會對證書進行多項檢查,如果檢查不通過,就會用告警,不過這些也只是告警而已,他不會

禁止你訪問。常用的瀏覽器(如FireFox、Chrome)會給你提供兩種方案:第一種方案是你可以選擇繼續訪問,這樣在你關閉瀏覽器之前,可以

訪問包含該根URL下的所有URL,但是當你關閉瀏覽器后,再次打開時還會有警告,我們可以認為,瀏覽器只是臨時把證書添加到了受信任的證書

頒發機構,關閉瀏覽器后,就把它刪除了。第二種方案是允許你永久將該證書添加到受信任的證書頒發機構,這樣,即使你關閉瀏覽器,再次打開后

該證書還有效。一般來說,我們會先嘗試第一種方案,檢驗一下URL是否可以正常訪問,如果還是無法訪問,那就要看一下服務器的web服務器軟件

是否設置有問題。

下面我們說一下其中的兩個檢查:

(1)證書是否是客戶端信任的CA簽發

    檢查證書的簽發機構是否是自己信任的CA,在客戶端有一個信任CA機構列表,如果不是,告警如圖2所示,這是FireFox的警告,在警告

的技術細節中提示了原因:該證書因為其自簽名而不被信任如果想繼續訪問,那就選擇”添加例外...",點擊添加例外,會出現圖3,可以看

到一個選項“永久保存此例外”,如果不選,就是上面說到的瀏覽器提供的第一種方案,如果選中,那就是第二種方案。

                                                                         圖2
 
 
 
                                                                         圖3
 

(2)證書中的Common Name與HTTP Request Header中的host(不包括端口)是否相同

     如果不同,警告如圖4所示,這是Chrome的警告。比如,我的證書的Common Name是主機的局域網IP=192.168.1.100,而我使用服務器的域名

www.xiaobai.net進行的訪問,這時就會提示提示“您嘗試訪問的是 www.xiaobai.net,但實際上訪問的卻是標識為 192.168.1.100 的服務”。

(注:如果局域網內的主機通過192.168.1.100訪問服務器,它會出現(1)中的警告,該證書不是受信任的證書頒發機構頒發的。)

      前面提到Chrome對於不信任的證書會有告警,但也提供了兩種方案使用他們:第一種方案是選擇”繼續www.xiaobai.net(不安全)",它是臨時性

將證書添加到受信任的證書頒發機構;第二種方案是將證書導出,添加到受信任的證書頒發機構,見http://www.cnblogs.com/ajianbeyourself/p/3899729.html

                                                                              圖4

五、找一家CA機構

     要獲取受瀏覽器信任的證書,則需要到證書提供商處申請。證書授證中心,又叫做CA機構,為每個使用公開密鑰的用戶發放一個數字證書。瀏覽器在默認情況下內置了一些CA機構的證書,

使得這些機構頒發的證書受到信任。VeriSign即 是一個著名的國外CA機構,工行、建行、招行、支付寶、財付通等網站均使用VeriSign的證書,而網易郵箱等非金融網站采用的是中國互

聯網信息中心CNNIC頒發的SSL證書,不過知乎上有人說CNNIC的證書不可信,呵呵,我同意。一個證書的價格從一百到數千,以VeriSign的證書為例,價格在每年8000元人民幣左右。

     也有免費的證書可以申請,StartSSL就是,它的根證書很久之前就被一些具有開源背景的瀏覽器支持(Firefox瀏覽器、谷歌Chrome瀏覽器、蘋果Safari瀏覽器等)。后來StartSSL竟然

搞定了微軟:在升級補丁中,微軟更新了通過Windows根證書認證(Windows Root Certificate Program)的廠商清單,並首次將StartCom公司列入了該認證清單。現在,在Windows 7

或安裝了升級補丁的Windows Vista或Windows XP操作系統中,系統會完全信任由StartCom這類免費數字認證機構認證的數字證書,從而使StartSSL也得到了IE瀏覽器的支持。

(來源及申請步驟)。在StartSSL提供了免費和收費兩種證書,見https://www.startssl.com/?app=37,其中Class1就免費的,它只驗證域名所有者,其它的都是收費的。這里我們只說一

下這種免費的證書的申請,在Class1中需要驗證你是域名的所有者:"Domain Name Validation",在你輸入域名后,它會彈出一個郵箱列表,如下,前三個郵箱是postmaster@你的域名,

hostmaster@你的域名,webmaster@你的域名,還有一個是你注冊域名時提供的郵箱,選擇一個,點擊“Continue”,它會給你郵箱把一個驗證碼

詳細的申請過程見http://www.live-in.org/archives/1296.html

 

六、只針對注冊、登陸進行https加密處理

既然HTTPS能保證安全,為什么全世界大部分網站都仍舊在使用HTTP呢?使用HTTPS協議,對服務器來說是很大的負載開銷。從性能上考慮,我 們無法做到對於每個用戶的每個訪問請求都進行安全加密(當然,Google這種大神除外)。作為一個普通網站,我們所追求的只是在進行交易、密碼登陸等操 作時的安全。通過配置Nginx服務器,可以使用rewrite來做到這一點。

在https server下加入如下配置:

if ($uri !~* "/logging.php$") { rewrite ^/(.*)$ http://$host/$1 redirect; }

在http server下加入如下配置:

if ($uri ~* "/logging.php$") { rewrite ^/(.*)$ https://$host/$1 redirect; }

這樣一來,用戶會且只會在訪問logging.php的情況下,才會通過https訪問。

更新:有一些開發框架會根據 $_SERVER['HTTPS'] 這個 PHP 變量是否為 on 來判斷當前的訪問請求是否是使用 https。為此我們需要在 Nginx 配置文件中添加一句來設置這個變量。遇到 https 鏈接重定向后會自動跳到 http 問題的同學可以參考一下。

server {
    ...
    listen 443; location \.php$ { ... include fastcgi_params; fastcgi_param HTTPS on; # 多加這一句 } }   server { ... listen 80; location \.php$ { ... include fastcgi_params; } }

參考鏈接:

http://www.lovelucy.info/nginx-ssl-certificate-https-website.html 
http://zou.lu/nginx-https-ssl-module
http://blog.s135.com/startssl/
http://www.baalchina.net/2008/08/nginx-https-rewrite/


免責聲明!

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



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