国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

SSL/TLS及證書概述

FullStackDeveloper / 1902人閱讀

摘要:數字簽名數字簽名就是非對稱加密摘要算法,其目的不是為了加密,而是用來防止他人篡改數據。認證是通過證書來達到的,而密碼交換是通過證書里面的非對稱加密算法公私鑰來實現的。

每次配置HTTPS或者SSL時,都需要指定一些cacert,cert,key之類的東西,他們的具體作用是什么呢?為什么配置了他們之后通信就安全了呢?怎么用openssl命令來生成它們呢?程序中應該如何使用這些文件呢?

本篇以TLS 1.2作為參考,只介紹原理,不深入算法的細節

SSL和TLS的關系

SSL(Secure Sockets Layer)和TLS(Transport Layer Security)的關系就像windows XP和windows 7的關系,升級后改了個名字而已。下面這張表格列出了它們的歷史:

協議 創建時間 創建者 RFC 注釋
SSL1.0 n/a Netscape n/a 由于有很多安全問題,所以網景公司沒有將它公之于眾
SSL2.0 1995 Netscape n/a 這是第一個被公眾所了解的SSL版本
SSL3.0 1996 Netscape rfc6101 由于2.0還是被發現有很多安全問題,Netscape于是設計了3.0,并且IETF將它整理成RFC發布了出來
TLS1.0 1999 IETF rfc2246 TLS 1.0基于SSL 3.0,修改不大,在某些場合也被稱之為SSL 3.1,改名主要是為了和Netscape撇清關系,表示一個新時代的來臨。類似于飯店換老板了,然后改了個名字,廚師還是原來的
TLS1.1 2006 IETF rfc4346
TLS1.2 2008 IETF rfc5246
TLS1.3 TBD IETF TBD 還在開發過程中,draft

最初的SSL只支持TCP,不過現在已經可以支持UDP了,請參考Datagram Transport Layer Security Version 1.2

HTTPS和TLS的關系

HTTPS=HTTP+TLS,其它的協議也類似,如FTPS=FTP+TLS。

注意:SSH和SSL/TLS是兩個不同的協議,SSH并不依賴于SSL/TLS

加密相關的概念

在正式開始介紹TLS之前,先澄清一些跟加密相關的概念:

對稱加密

這是我們加密文件常用的方式,加密的時候輸入一個密碼,解密的時候也用這個密碼,加密和解密都用同一個密碼,所以叫對稱加密。常見的算法有AES、3DES。

非對稱加密

非對稱加密是一個很神奇的東西,它有兩個不一樣的密碼,一個叫私鑰,另一個叫公鑰,用其中一個加密的數據只能用另一個密碼解開,用自己的都解不了,也就是說用公鑰加密的數據只能由私鑰解開,反之亦然。

私鑰一般自己保存,而公鑰是公開的,同等加密強度下,非對稱加密算法的速度比不上對稱加密算法的速度,所以非對稱加密一般用于數字簽名和密碼(對稱加密算法的密碼)的交換。常見的算法有RSA、DSA、ECC。

摘要算法

摘要算法不是用來加密的,其輸出長度固定,相當于計算數據的指紋,主要用來做數據校驗,驗證數據的完整性和正確性。常見的算法有CRC、MD5、SHA1、SHA256。

數字簽名

數字簽名就是“非對稱加密+摘要算法”,其目的不是為了加密,而是用來防止他人篡改數據。

其核心思想是:比如A要給B發送數據,A先用摘要算法得到數據的指紋,然后用A的私鑰加密指紋,加密后的指紋就是A的簽名,B收到數據和A的簽名后,也用同樣的摘要算法計算指紋,然后用A公開的公鑰解密簽名,比較兩個指紋,如果相同,說明數據沒有被篡改,確實是A發過來的數據。假設C想改A發給B的數據來欺騙B,因為篡改數據后指紋會變,要想跟A的簽名里面的指紋一致,就得改簽名,但由于沒有A的私鑰,所以改不了,如果C用自己的私鑰生成一個新的簽名,B收到數據后用A的公鑰根本就解不開。

TLS握手過程

TLS主要包含兩部分協議,一部分是Record Protocol,描述了數據的格式,另一部分是Handshaking Protocols,描述了握手過程,本篇中只介紹握手過程,不介紹具體的通信數據格式。

握手的目的有兩個,一個是保證通信的雙方都是自己期待的對方,任何一方都不可能被冒充,另一個是交換加密密碼,使得只有通信的雙方知道這個密碼,而別人不知道。前一個就是我們常說的認證,而后一個就是密碼交換。認證是通過證書來達到的,而密碼交換是通過證書里面的非對稱加密算法(公私鑰)來實現的。

先看握手的交互圖:

+--------+                                      +--------+
|        |   1. ClientHello                     |        |
|        |------------------------------------->|        |
|        |                                      |        |
|        |   2. ServerHello                     |        |
|        |   3. Certificate                     |        |
|        |   4. ServerKeyExchange (optional)    |        |
|        |   5. CertificateRequest (optional)   |        |
|        |   6. ServerHelloDone                 |        |
|        |<------------------------------------ |        |
| Client |                                      | Server |
|        |   7. Certificate (optional)          |        |
|        |   8. ClientKeyExchange               |        |
|        |   9. CertificateVerify (optional)    |        |
|        |  10. Finished                        |        |
|        |------------------------------------> |        |
|        |                                      |        |
|        |  11. Finished                        |        |
|        |<------------------------------------ |        |
+--------+                                      +--------+

注意: 下面解釋過程中用到的具體協議版本、算法和值都是示例,實際中可能不是這些

ClientHello

client->server: 
hello,咱建立個連接唄,我這邊的支持的最高版本是TLS1.1,
支持的密碼套件(cipher suite)有“TLS_RSA_WITH_AES_128_CBC_SHA”和“TLS_RSA_WITH_AES_256_CBC_SHA256”,
支持的壓縮算法有DEFLATE,我這邊生成的隨機串是abc123456。

這里有幾點需要解釋一下:

客戶端會把自己最喜歡的密碼套件放在最前面,這樣服務器端就會根據客戶端的要求優先選擇排在前面的算法套件

密碼套件就是一個密碼算法三件套,里面包含了一個非對稱加密算法,一個對稱加密算法,以及一個數據摘要算法。以TLS_RSA_WITH_AES_128_CBC_SHA為例,RSA是非對稱加密算法,表示后面用到的證書里面的公鑰用的是RSA算法,通信的過程中需要簽名的地方也用這個算法,并且密碼(key)的交換過程也使用這個算法;AES_128_CBC是對稱加密算法,用來加密握手后傳輸的數據,其密碼由RSA負責協商生成;SHA是數據摘要算法,表示后面交換的證書里簽名
用到的摘要算法是sha1,并且后續通信過程中需要用到數據校驗的地方也是用的這個算法。在Record Protocol協議中,摘要算法是必須的,即數據包都需要有校驗碼,而簽名是可選的。

ClientHello里面還可以包含session id,即表示重用前面session里的一些內容,比如已經協商好的算法套件等,服務器收到session id后會去內存里面找,如果這是一個合法的session id,那么它就可以選擇重用前面的session,這樣可以省去很多握手的過程。為了簡化討論,這里不介紹session重用的問題。

ServerHello

server收到client的hello消息后,就在自己加載的證書中去找一個和客戶支持的算法套件相匹配的證書,并且挑選一個自己也支持的對稱加密算法(證書里面只有非對稱加密和摘要算法,不包含對稱加密算法)。如果出現下面幾種情況,握手失?。?/p>

客戶端支持的TLS版本太低,比如server要求最低版本為1.2,而客戶端支持的最高版本是1.1

根據客戶端所支持的密碼套件,找不到相應要求的證書

無法就支持的對稱加密算法達成一致

如果一切都OK,那么服務器端將返回ServerHello:

server->client: 
hello,沒問題,我們就使用TLS1.1吧,
算法采用“TLS_RSA_WITH_AES_256_CBC_SHA256”,這個加密強度更高更安全,
壓縮就算了,我這邊不支持,我這邊生成的隨機數是654321def。

如果server支持session重用的話,這里還會返回session id

Certificate

服務器在發送完ServerHello之后緊接著發送Certificate消息,里面包含自己的證書。

當然這步在有些情況下可以忽略掉,就是非對稱加密算法選擇使用dh_anon,當然這是特殊的情況,并且也不安全,所以這里就不展開討論。

server->client: 這是我的證書(身份證),請過目

ServerKeyExchange(可選)

在前面的ServerHello中,雙方已經協商好了密碼套件,對于套件里面的非對稱加密算法,有些需要更多的信息才能生成一個可靠的密碼,而有些不需要,比如RSA,就不需要發送這個消息,客戶端自己生成一個準密碼(premaster)就可以了,而有些算法,比如DHE_RSA,就需要發送一點特殊的信息給客戶端,便于它生成premaster。

premaster可以理解為最終密碼的初級版本,有了這個密碼之后,稍微再做一下計算就可以得到最終要使用的對稱加密的密碼

server->client: 這是生成premaster所需要的一些信息,請查收

CertificateRequest(可選)

只有在需要驗證客戶端的身份的時候才用得著,在大部分情況下,尤其是HTTPS,這一步不需要。比如我們訪問銀行的網站,我們只要保證那確實是銀行的網站就可以了,銀行驗證我們是通過賬號密碼,而不是我們的證書。而U盾就是一個驗證客戶端的例子,銀行給你的U盾里面有你的證書,你通過U盾訪問銀行的時候,銀行會驗證U盾里面證書是不是你的,這種情況下,你和銀行之間進行TLS握手的時候,銀行會給你發這個CertificateRequest請求。

server->client: 把你的證書(身份證)也給我看看,我要確認一下你是不是XXX。

ServerHelloDone

server->client: 我要告訴你的就是這么多了,處理完了給我個回話吧。

Certificate(可選)

如果客戶端在前面收到了服務器的CertificateRequest請求,那么將會在這里給服務器發送自己的證書,就算自己沒有證書,也要發送這個消息告訴服務器端自己沒有證書,然后由服務器端來決定是否繼續。

client->server: 這是我的證書(身份證),請過目

ClientKeyExchange

客戶端驗證完服務器端的證書后(怎么驗證證書將在后面介紹),就會生成一個premaster,生成的方式跟采用的密碼交換算法有關,以TLS_RSA_WITH_AES_128_CBC_SHA為例,其密碼交換算法是RSA,于是客戶端自己直接生成一個48字節長度的premaster即可,不需要服務器發過來的ServerKeyExchange。

client->server: 
這是計算真正密碼要用到的premaster,它是用你證書里的公鑰加密了的哦,
記得用你的私鑰解密后才能看到哦

CertificateVerify(可選)

如果客戶端給服務器發了證書,就需要發送該消息給服務器,主要用于驗證證書對應的私鑰確實是在客戶端手里。

client->server: 
這是一段用我私鑰加密的數據,你用我給你的證書里的公鑰解密看看,
如果能解開,說明我沒騙你,私鑰確實是在我手里,
并不是我隨便找了一個別人的證書忽悠你

發送的消息里面都帶有校驗碼,所以解密后計算下校驗碼,能對上說明解密成功

Finished

當前面的過程都沒問題后,服務器和客戶端都根據得到的信息計算對稱加密用的密碼,這是RFC里面給出的計算方法:

master_secret = PRF(pre_master_secret, "master secret",
                          ClientHello.random + ServerHello.random)
                          [0..47];

雖然不太了解PRF的細節,但至少客戶端和服務器端用的算法和輸入都是一樣的,所以得到的master密碼也是一樣的。這里pre_master_secret就是ClientKeyExchange里面客戶端發給服務器端的premaster,ClientHello.random和ServerHello.random分別是握手開始時雙方發送的hello請求中的隨機字符串。

這里加入隨機數的原因主要是為了防止重放攻擊,保證每次握手后得到的密碼都是不一樣的

然后雙方將自己緩存的握手過程中的數據計算一個校驗碼,并用對稱加密算法和剛算出來的master密碼加密,發給對方,這一步有兩目的,一個是保證雙方算出來的master密碼都是一樣的,即我這邊加密的數據你那邊能解開;另一個目的是確保我們兩個人的通信過程中的每一步都沒有被其他人篡改,因為握手的前半部分都是明文,所以有可能被篡改,只要雙方根據各自緩存的握手過程的數據算出來的校驗碼是一樣的,說明中間沒人篡改過。

client->server: 這是用我們協商的對稱加密算法和密碼加密過的握手數據的指紋,看能不能解開,并且和你那邊算出來的指紋是一樣的
server->client: 這是用我們協商的對稱加密算法和密碼加密過的握手數據的指紋,你也看看能不能解開,并且和你那邊算出來的指紋是一樣的

如果雙方發送完Finished而對方沒有報錯,握手就完成了,雙發都得到了密碼,并且這個密碼別人不知道,后續的所有數據傳輸過程都會用這個密碼進行加密,加密算法就是ServerHello里面協商好的對稱加密算法。

在上面握手的過程中,一旦有任何一方覺得有問題,都可能隨時終止握手過程

握手不成功常見問題

配置好了之后還是連不上,一般會是下面幾種問題:

版本不一致,有一方的版本太低,另一方為了安全不同意跟它通信

無法就cipher suite達成一致,有一方支持的加密算法太弱,安全程度不夠

證書有問題,沒法通過驗證

服務器端需要驗證客戶端的證書,而客戶端沒有配置

證書相關

開始之前,看看我們常說的那些跟證書相關的概念

基本概念

私鑰

私鑰就是一個算法名稱加上密碼串,自己保存,從不給任何人看

公鑰

公鑰也是一個算法名稱加上密碼串,一般不會多帶帶給別人,而是嵌在證書里面一起給別人

CA

專門用自己的私鑰給別人進行簽名的單位或者機構

申請(簽名)文件

在公鑰的基礎上加上一些申請人的屬性信息,比如我是誰,來自哪里,名字叫什么,證書適用于什么場景等的信息,然后帶上進行的簽名,發給CA(私下安全的方式發送),帶上自己簽名的目的是為了防止別人篡改文件。

證書文件

證書由公鑰加上描述信息,然后經過私鑰簽名之后得到,一般都是一個人的私鑰給另一個人的公鑰簽名,如果是自己的私鑰給自己的公鑰簽名,就叫自簽名。

簽名過程

CA收到申請文件后,會走核實流程,確保申請人確實是證書中描述的申請人,防止別人冒充申請者申請證書,核實通過后,會用CA的私鑰對申請文件進行簽名,簽名后的證書包含申請者的基本信息,CA的基本信息,證書的使用年限,申請人的公鑰,簽名用到的摘要算法,CA的簽名。

簽完名之后,證書就可以用了。

證書找誰簽名合適

別人認不認你的證書要看上面簽的是誰的名,所以簽名一定要找權威的人來簽,否則別人不認,哪誰是權威的人呢?那就是CA,哪些CA是受人相信的呢?那就要看軟件的配置,配置相信誰就相信誰,比如瀏覽器里面默認配置的那些,只要是那些CA簽名的證書,瀏覽器都會相信,而你自己寫的程序,可以由你自己指定信任的CA。

信任一個CA就是說你相信你手上拿到的CA的證書是正確的,這是安全的前提,CA的證書是怎么到你手里的,這個不屬于規范的范疇,不管你是U盤拷貝的,還是怎么弄來得,反正你得確保拿到的CA證書沒問題,比如瀏覽器、操作系統等,安裝好了之后里面就內置了很多信任的CA的證書。

那么CA的證書又是誰簽的名呢?一般CA都是分級的,CA的證書都是由上一級的CA來簽名,而最上一級CA的證書是自簽名證書。

證書如何驗證

下面以瀏覽器為例,說明證書的驗證過程:

在TLS握手的過程中,瀏覽器得到了網站的證書

打開證書,查看是哪個CA簽名的這個證書

在自己信任的CA庫中,找相應CA的證書,

用CA證書里面的公鑰解密網站證書上的簽名,取出網站證書的校驗碼(指紋),然后用同樣的算法(比如sha256)算出出網站證書的校驗碼,如果校驗碼和簽名中的校驗碼對的上,說明這個證書是合法的,且沒被人篡改過

讀出里面的CN,對于網站的證書,里面一般包含的是域名

檢查里面的域名和自己訪問網站的域名對不對的上,對的上的話,就說明這個證書確實是頒發給這個網站的

到此為止檢查通過

如果瀏覽器發現證書有問題,一般是證書里面的簽名者不是瀏覽器認為值得信任的CA,瀏覽器就會給出警告頁面,這時候需要謹慎,有可能證書被掉包了。如訪問12306網站,由于12306的證書是自己簽的名,并且瀏覽器不認為12306是受信的CA,所以就會給警告,但是一旦你把12306的根證書安裝到了你的瀏覽器中,那么下次就不會警告了,因為你配置了瀏覽器讓它相信12306是一個受信的CA。

證書生成示例

下面以實際的例子來看看怎么生成證書。

生成CA的私鑰和證書

#創建一個cert目錄,后續操作都在該目錄下進行
dev@dev:~$ mkdir cert && cd cert

dev@dev:~/cert$ openssl req -newkey rsa:2048 -nodes -sha256 -keyout ca.key -x509 -days 365 -out ca.crt
......
Common Name (e.g. server FQDN or YOUR name) []:ca.com
......

-newkey rsa:2048:生成一個長度為2048的采用RSA算法的私鑰

-nodes:這個私鑰在本地存儲的時候不加密(可以通過其它參數來加密私鑰,這樣存儲比較安全)

-sha256:生成的證書里面使用sha256作為摘要算法

-keyout ca.key: 輸出私鑰到key.pem

-x509:證書文件格式為x509,目前TLS默認只支持這種格式的證書

-days 365:證書有效期1年

-out ca.crt:生成的證書文件保存到ca.crt

生成的過程中會要求填一些信息,除了Common Name要取一個容易區分的名字之外,其它都可以隨便填寫,我們在這里將它填為ca.com.

生成私鑰和證書簽名申請文件

dev@dev:~/cert$ openssl req -newkey rsa:2048 -nodes -sha256 -keyout domain.key -new -out domain.csr
......
Common Name (e.g. server FQDN or YOUR name) []:domain.com
......

#這里將CN設置成domain.com

這里和上面的區別就是這里是-new生成一個證書簽名申請文件,而上面用-x509生成一個自簽名文件,其它的參數意義都一樣。

從這里可以看出,CA的私鑰和普通人的私鑰沒什么區別,唯一的區別就是CA用私鑰自簽名的證書受別人相信,而普通人的自簽名證書別人不信,所以需要CA來給證書簽名。

使用CA的私鑰對申請文件進行簽名

dev@dev:~/cert$ openssl x509 -CA ca.crt -CAkey ca.key -in domain.csr -req -days 365 -out domain.crt -CAcreateserial -sha256

由于需要往生成的證書里寫入簽名者的信息,所以這里需要ca.crt,因為只有這里有CA的描述信息,ca.key里面只有私鑰的信息。

查看證書內容

上面生成的證書文件格式都是pem格式。通過下面這個命令可以看到證書的內容:

dev@dev:~/cert$ openssl x509 -text -noout -in ca.crt
dev@dev:~/cert$ openssl x509 -text -noout -in domain.crt
程序支持TLS需要哪些文件

回到最開始的問題,cacert,cert,key對應于上面的哪些東西呢? cacert就是CA的證書,cert就是程序自己的證書,key就是程序自己的私鑰。對于服務器來說,至少需要有自己的私鑰和證書,而對于客戶端來說,至少需要一個cacert,不然沒法驗證服務器的證書是否正確。

TLS開發示例 server

服務器采用python開發,只需要指定server的私鑰和證書就可以了,代碼如下:

import BaseHTTPServer, SimpleHTTPServer
import ssl

httpd = BaseHTTPServer.HTTPServer(("localhost", 443), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, keyfile="./domain.key", certfile="./domain.crt", server_side=True)
httpd.serve_forever()

將上面的代碼保存為server.py,然后啟動服務:

#監聽443端口需要root權限
dev@dev:~/cert$ sudo python server.py
client

這里使用大家都熟悉的curl作為客戶端來測試:

#直接訪問報錯,提示證書驗證失敗,
#那是因為domain.crt是我們自己的CA簽名的,curl根本就不認識,更談不上相信它了
dev@dev:~/cert$ curl https://127.0.0.1
curl: (60) server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
More details here: http://curl.haxx.se/docs/sslcerts.html
......

#參數中顯式的指定我們CA的證書,讓它成為curl信任的CA,這樣curl就認為我們的證書沒問題了
#但curl還是報錯,說這個證書是發給domain.com的,而不是127.0.0.1
dev@dev:~/cert$ curl --cacert ./ca.crt https://127.0.0.1
curl: (51) SSL: certificate subject name (domain.com) does not match target host name "127.0.0.1"

#往/etc/hosts加上一條記錄,設置域名domain.com的ip地址為127.0.0.1
dev@dev:~/cert$ sudo sh -c "echo "127.0.0.1 domain.com" >> /etc/hosts"

#然后通過域名來訪問,得到了服務器的正確返回
dev@dev:~/cert$ curl --cacert ./ca.crt  https://domain.com

Directory listing for /

Directory listing for /



#測試完成之后記得手動將domain.com從/etc/hosts里面刪掉
參考

Transport Layer Security
OpenSSL Essentials: Working with SSL Certificates, Private Keys and CSRs

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/11243.html

相關文章

  • nginx服務器配置StartSSL證書

    摘要:概述基礎服務器操作系統服務器免費認證服務協議運行機制的概述百度百科解釋安全套接層及其繼任者傳輸層安全,是為網絡通信提供安全及數據完整性的一種安全協議。通過驗證的郵件的,輸入到瀏覽器中進行下一步安裝證書。配置訪問重啟訪問訪問域名顯示工作正常。 概述 ssl基礎服務器操作系統:aliyun ubuntu 12.04WEB服務器:nginx 1.4.x免費ssl認證服務:startssl...

    Hanks10100 評論0 收藏0
  • 沒那么淺地談談HTTP與HTTPS【三】

    摘要:公開密鑰加密的出現大大減輕了交換對稱密鑰的困難,公鑰可以公開透過不安全可被竊聽的渠道發送,用以加密明文。當與配合使用,稱之為,與配合則稱為,以此類推。這步沒有簽名,服務端收到數據后不會發現被篡改。對于認證機構,一旦私鑰外泄,將可能導致整未濟,亨。小狐汔濟,濡其尾,無攸利?!兑住妨⒚荑€管理當不再擔心身份會被冒充、篡改之后,我們再來詳細談談網絡通信中對于加密算法的密鑰管理。在密鑰被簽發后,...

    Tecode 評論0 收藏0

發表評論

0條評論

FullStackDeveloper

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<