加密解密
Base64編解碼
在參數傳輸的過程中經常遇到的一種情況:使用全英文的沒問題,但一旦涉及到中文就會出現亂碼情況。與此類似,網絡上傳輸的字符並不全是可打印的字符,比如二進制文件、圖片等。Base64的出現就是為了解決此問題,它是基於64個可打印的字符來表示二進制的數據的一種方法。
我們知道在計算機中任何數據都是按ascii碼存儲的,而ascii碼的128~255之間的值是不可見字符。而在網絡上交換數據時,比如說從A地傳到B地,往往要經過多個路由設備,由於不同的設備對字符的處理方式有一些不同,這樣那些不可見字符就有可能被處理錯誤,這是不利於傳輸的。所以就先把數據先做一個Base64編碼,統統變成可見字符,這樣出錯的可能性就大降低了。
Base64索引表:['A','B'...'a','b',...'0','1',...'+','/']
轉換步驟:
- 待轉換字符串每3個字節分為一組,共24位
- 將上面24位每6個一組分為4組
- 在每組前面添加兩個0,總共32位,即4個字節
- 根據上面Base64索引表獲得相應的值
因此Base64編碼之后的文本要比原文大約三分之一
如果位數不足,依舊是每6分字節一組,不足的用0補齊,后面沒有對應數據的用=
補齊.

Base64是一種任意二進制到文本字符串的編碼方法,常用於在URL、Cookie、網頁中傳輸少量二進制數據。在項目中,將報文進行壓縮、加密后,最后一步必然是使用base64編碼,因為base64編碼的字符串更適合不同平台、不同語言的傳輸.
SHA-256 哈希函數
一個n
位的哈希函數就是一個從任意長的消息到n
位哈希值的映射,這樣的函數是目前在數字簽名和密碼保護當中極為重要的手段。當前比較流行的哈希函數主要有128位的MD4和MD5和160位的SHA-1,今天介紹的SHA-2(Secure Hash Algorithm 2)族有着更多位的輸出哈希值,破解難度更大,能夠提高更高的安全性.
對於任意長度的消息,SHA256都會產生一個256位的哈希值,稱作消息摘要,通常用64個十六進制字符串表示.
稱謂: 單向散列函數, 哈希函數, 雜湊函數, 消息摘要函數
輸入: 原像
輸出: 散列值, 哈希值, 指紋, 摘要
常見的應用場景有: 數據庫中保護用戶密碼、防止文件篡改、數字簽名、偽隨機數生成、秒傳等.
RSA加密算法
RSA是目前最有影響力和最常用的公鑰加密算法(非對稱加密),可以說是公鑰加密算法的事實標准。
公鑰=(E,N)
私鑰=(D,N)
密鑰對=(E,D,N)
所以生成密鑰對就是求E、D、N.
- N: 准備兩個互質數p,q。這兩個數不能太小,太小則會容易破解,將p乘以q就是N。如果互質數p和q足夠大,那么根據目前的計算機技術和其他工具,至今也沒能從N分解出p和q。換句話說,只要密鑰長度N足夠大(一般1024足矣),基本上不可能從公鑰信息推出私鑰信息。
- L: p-1 和 q-1的最小公倍數,即lcm(p-1,q-1)
- E: E是一個比1大比L小的數,E和L的最大公約數為1.
- D: 數D是由數E計算出來的,數D必須保證足夠大.1 < D < L; E*D mod L = 1.只要D滿足上述2個條件,則通過E和N進行加密的密文就可以用D和N進行解密.
因此RSA公鑰加密體制包含三個算法:
(PK,M)<---KeyGen(): 密鑰生成算法,
是安全常數,值越大,質數p越大
CT <---Encrypt(PK,M): 加密算法
M <---Decrypt(SK,CT): 解密算法
但是公鑰加密會面臨中間人攻擊的危險, 所以我們要確保公鑰必須是我們想要發送的對方的公鑰,而不是其他人頂替的.這就需要給公鑰簽名.
非對稱加密算法除了支持加密外,還可以實現簽名.
簽名過程: 使用發送方私鑰對消息摘要加密, 生成消息簽名, 接收方公鑰生成密文發送出去(防止hash值也被篡改)
驗簽過程: 使用接收方私鑰對密文進行解密, 獲得消息和消息簽名; 使用發送方公鑰解密消息簽名, 獲得消息摘要; 使用相同哈希算法生成消息摘要進行對比,如果相同驗簽成功.

RSA簽名體制同樣包含三個算法:
(PK,SK)<---KeyGen()
<---Sign(SK,M): 簽名算法以私鑰SK和待簽名的消息M作為輸入,輸出簽名
b <---Verify(PK,,M): 驗證算法以公鑰PK,簽名
以及消息M作為輸入,輸出一個比特值b。b=1意味着驗證通過。b=0意味着驗證不通過
HTTPS加密過程和證書驗證過程
首先https=http+tls. TLS是基於TCP協議之上的,由SSL發展而來.TLS協議的優勢是與高層應用層協議無耦合,應用層協議能夠透明的運行在TLS協議之上,由TLS協議進行創建加密通道需要的協商和認證。應用層協議傳送的數據在通過TLS協議時都會被加密,從而保證通信的私密性。
基本過程是: 客戶端像服務器端索要公鑰;雙方生成“對話密鑰”;雙方采用“對話密鑰”進行通信.
問題:
-
如何保證公鑰不被篡改?
將公鑰放在證書里,只要證書可信,公鑰就是可信的.
-
公鑰加密計算量太大,如何減少耗用時間?
每一次對話(session),客戶端和服務器端都生成一個"對話密鑰"(session key),用它來加密信息。由於"對話密鑰"是對稱加密,所以運算速度非常快,而服務器公鑰只用於加密"對話密鑰"本身,這樣就減少了加密運算的消耗時間。
TLS協議流程
一旦客戶端和服務器都同意使用TLS協議,他們通過一個握手過程協商出一個有狀態的連接以傳輸數據.這通常發生在TCP連接建立以后.具體過程為:
-
客戶端發送TLS版本號+所支持加密套件列表(加密算法、哈希算法)+客戶端生成的隨機數+希望使用的TLS選項
-
服務器端選擇一個客戶端加密套件+自己的證書+服務端生成的隨機數+希望使用的TLS選項+(要求客戶端證書)
-
客戶端驗證服務器身份后,取出證書中的公鑰,發送(自己證書)+使用服務器公鑰加密一個隨機數(此時雙方各有三個相同隨機數,用於生成會話密鑰)
為什么需要三個隨機數?
客戶端和服務器加上pre master secret三個隨機數一同生成的密鑰就不容易被猜出了,一個偽隨機可能完全不隨機,可是是三個偽隨機就十分接近隨機了,每增加一個自由度,隨機性增加的可不是一.
-
服務器端使用私鑰解密出信息后,計算生成會話密鑰,發送加密的finish消息,表明完成握手,接下來進行的通信就是普通的http協議,只不過發送的是加密過的消息.
證書驗證過程
證書簽發過程:
- 撰寫證書元數據信息
- 通過Hash算法計算出消息摘要
- 然后用CA機構的私鑰對消息摘要加密,生成簽名,附在文件證書上,使之變成一個簽名過的證書.
證書驗證過程:
- 客戶端獲得站點的證書,解碼后獲得元數據信息和簽名,要驗證站點可信后,才能使用其公鑰,因此客戶端找到其站點證書頒發者的信息
- 站點證書的頒發者驗證了服務端站點是可信的,但客戶端依然不清楚該頒發者是否可信
- 再往上回溯,找到了認證了中間證書商的根證書頒發者。由於根的證書頒發者非常少,我們瀏覽器之前就認識了,因此可以認為根證書頒發者是可信的;
- 一路倒推,證書頒發者可信,那么它所頒發的所有站點也是可信的,最終確定了我們所訪問的服務端是可信的;
- 客戶端使用證書中的公鑰,繼續完成
TLS
的握手過程
自簽證書
首先,X.509是一個標准,規范了公開秘鑰認證、證書吊銷列表、授權憑證、憑證路徑驗證算法等。X.509證書包含三個文件: .key、.csr、.crt(.pem),分別是私鑰、證書簽名請求文件、簽名后的證書.
我們可以使用openssl命令行工具給自己簽證書,用於測試使用或內部系統使用,但這樣會被瀏覽器提示未認證的簽名機構,需要我們自己信任該證書,不過有的瀏覽器可能對於私有證書會直接拒絕不給提示的機會.
自簽證書相當於把自己生成的證書簽名請求文件,用自己的私鑰去做簽名,相當於CA證書,自己給自己做驗證.這個證書還可以給其他客戶端去做前面,這樣當我們有多個客戶端的時候,只需要在客戶端安裝根證書就可以了,不必重復安裝客戶端證書.
X.509證書有兩種編碼格式:
- PEM: 是明文格式的, 以 -----BEGIN CERTIFICATE-----開頭,已-----END CERTIFICATE-----結尾,中間是經過base64編碼的內容,apache需要的證書就是這類編碼的證書 查看這類證書的信息的命令為 :openssl x509 -noout -text -in server.pem
- DER: 是二進制格式的證書,查看這類證書的信息的命令為 :openssl x509 -noout -text -inform der -in server.der
我們遇到常用的證書擴展名.crt、.cer、.pem大部分都使用PEM編碼格式.
.key 一般公鑰或者密鑰都會用這種擴展名,可以是DER編碼的或者是PEM編碼的 查看DER編碼的(公鑰或者密鑰)的文件的命令為 openssl rsa -inform DER -noout -text -in xxx.key 查看PEM編碼的(公鑰或者密鑰)的文件的命令為 openssl rsa -inform PEM -noout -text -in xxx.key