您好,登錄后才能下訂單哦!
??信息加密技術經過多年的發展,由一些基本算法組合形成了許多成熟的應用,如數字簽名,安全證書,HTTPS,以及最近大熱的數字加密貨幣,區塊鏈等。這些看似種類繁多的應用,其實都由三類基本的算法通過不同的組合來實現,這三類算法分別是: 數據摘要(在很多場合也被稱作哈希運算),對稱加密,非對稱加密。本文拋開這三類算法在不同實現方案中的差異,抽象出各類算法的共性,提綱挈領地描繪出三類算法在加密體系中的應用場景,讓開發者能在短時間內對信息加密體系有個全局的認識,并能將這三類算法應用在實際的需求場景中,希望本文能成為設計信息加密應用的簡要手冊。
??閱讀建議:每類算法都以偽代碼給出函數聲明,不代表特定算法, 比如函數digest代表了在實際使用中的MD5, SHA1, RIPEMD160等實現了數據摘要功能的算法,讀者在閱讀過程中不要急于去考慮這些函數的實現,而應該去領會算法的特點和完成的功能。這些算法幾乎在所有主流的編程語言庫中都有具體實現,實在有很少的場合需要自己再去實現。對于有研究技術細節需求的讀者,可以在閱讀完本文后,對信息加密體系這棵樹有了全局的了解,再按圖索驥地去研究樹葉.
??下面將分別介紹這三類算法各自的特性和應用, 然后再對將這些算法組合起來的應用進行介紹.
??
byte[] digest(byte[] data)
??1.2.1. 無論data的長度為多少,digest返回某一定長數據,通常為幾十個字節
??1.2.2. 若digest(data1) != digest(data2),則data1 != data2;若digest(data1) = digest(data2)則可以認為有很高的概率data1 = data2,在特定的情況下,對某些算法來講,該判斷出錯的概率不到1/128^2。
??1.2.3. 運算不可逆,即知道digest的返回值,不能反推出data的值。順便提一句,人們常提起的比特幣挖礦其實就是指通過不斷的嘗試找出一個data,使得digest(data)的結果小于某一個表示難度的數,其基本代碼如下:
while(digest(blockData + random()) > difficultyFactor); //random()在這里產生隨機數
??可見即使為了得到滿足某一條件的data值,也只能通過暴力嘗試,而不能有其它快速的方法。
??1.2.4. digest函數相對于下面要談的其它兩類算法來說,運算速度非常快。注意是相對的快,因為即便如此挖礦也是個很費時的運算,呵呵。
??假設要做這么一個文件上傳系統,要求上傳文件前,先檢測服務器上是否已經有同樣的文件存在,如果已經存在,則不再上傳。如果沒有digest算法,只有把整個文件上傳到服務器再進行比較,這無疑非常費時。如果我們每次上傳文件,都對文件做一次摘要運算(特性1.2.4:摘要運算速度非常快,相對于文件上傳的耗時來說忽略不計),并將摘要值保存起來;那么下次上傳文件前我們對將要上傳的文件進行一次摘要運算,只是把摘要值提交到服務器(特性1.2.1:摘要值一般只有幾十個字節), 服務器在之前保存的摘要值列表中查找客戶端新提交上來的摘要值,如果找到了(特性1.2.2),則告訴客戶端不用再上傳了。這就是很多云盤使用的秒傳技術,很多上G的文件,只要幾秒鐘就上傳成功了,原因就在于其他人在你之前已經上傳過同樣的文件。
??還是上傳文件的例子,客戶端上傳前先把本地文件的摘要值傳給服務器,服務器在接收到完整的文件后,用同樣的摘要算法,計算接收到的文件的摘要值,和客戶端上傳的摘要值進行比較,如果相同則可以認為文件接收完整;反之則認為文件在傳輸過程中損壞(特性1.2.2)。
??設計一個簡單的充值磁條卡,所有磁卡機都能讀磁卡中的數據,但只有授權的磁卡機才能合法地寫入數據。其數據寫入的過程如下圖所示:
??
??寫入磁卡的數據分為兩部分,一部分是明文數據;一部分是摘要數據。這里的摘要數據有個術語叫簽名。簽名的生成過程很簡單,就是把密碼和明文數據拼接在一起作為digest函數的輸入,digest的輸出即為簽名。授權的磁卡機讀取磁條數據時先要驗證簽名,即把磁條的明文數據讀入內存,然后和密碼按照寫入時同樣的過程生成一個簽名,把該簽名和磁條上記錄的簽名做對比,如果簽名一樣則認為數據沒有被篡改,反之則認為已經被篡改。磁條上任何一個字節的修改,都不能通過簽名驗證過程。因為非授權磁卡機在不知道密碼的情況下,很難生成一個合法的簽名,雖然能讀取簽名,但也不能根據簽名推導出密碼(特性1.2.3).
??注意:在實際生產環境中,大部分情況下,簽名是在服務器端進行。為了加強安全性,產生簽名時還會加入一個隨機數,隨機數和明文一樣寫入磁條,同時參加簽名驗證過程。同時也還可以進行多遍摘要運算。這些措施都是為了進一步增加通過試探偽造簽名的難度。
??
byte [] symEncrypt(byte[] plainData,byte[] password);
byte [] symDecrypt(byte[] cipherData,byte[] password);
2.2.1. 加密和解密必須使用同樣的密匙。
2.2.2. 相對于非對稱加密速度快。
??不再贅述。
??
class KeyPair //密鑰對
{
byte [] privateKey //私鑰
byte [] publicKey; //公鑰
};
KeyPair generateKeyPair();//用于產生一個密鑰對
byte[] asyEncrypt(byte[] plainData,byte[] publicKey); //用公鑰對數據加密
byte[] asyDecrypt(byte[] cipherData,byte[] privateKey); //用私鑰對公鑰加密的數據解密
??3.2.1. 用公鑰加密的數據,只能由對應的私鑰解密。即他們都在由generateKeyPair產生的一個密鑰對(KeyPair)里面。有時也用私鑰加密,公鑰解密。
??3.2.2. 知道一個KeyPair的publicKey,以現在計算機的算力在短期內無法計算出它對應的privateKey。這個短期指的是至少幾十年。
??3.2.3. 非對稱加密通常比對稱加密慢很多。所以它通常只用來對密鑰或摘要加解密,而不會用在長數據上。
??設計一個文件上傳系統,要求所有終端上傳的數據都經過加密,即使數據經過被竊聽的網絡,竊聽者也無法獲知數據內容。如果使用對稱加密會發生什么:
??1. 所有終端和服務器共享一個秘鑰,任何一個終端泄露了秘鑰,數據傳輸將不再安全。
??2. 為每個終端分配一個秘鑰,服務器保存每個終端的秘鑰,從不同終端來的數據使用對應終端的秘鑰來解密。這可以解決一個終端泄密,導致整個系統泄密的問題。但同樣存在秘鑰泄露的風險。
??這時候使用非對稱加密就解決了上面的所有問題。首先用generateKeyPair生成一個密鑰對(KeyPair),將KeyPair的publicKey分配給所有終端,將KeyPair的privateKey安全保存在服務器。終端上傳數據時使用asyEncrypt(byte[] plainData,byte[] publicKey)加密數據,服務器端用asyDecrypt(byte[] cipherData,byte[] privateKey)解密數據。因為公鑰加密的數據只能通過對應的私鑰來解密(特性3.2.1),所以數據即使在傳播途中被竊聽也是安全的,又因為特性3.2.2,即使所有人知道公鑰,私鑰也是安全的。
??上述設計方案只是為了演示非對稱加密方案的使用,在現實中一般不會這么做,因為特性3.2.3,這樣會存在性能問題。所以一般會與對稱加密組合使用,我們接著就要介紹這種用法。
??
??繼續上文的例子,由于非對稱加密的速度非常慢,所以我們考慮只用它來加密數據量小的一個臨時密鑰,用這個臨時密鑰來使用對稱加密的方法加密實際的通信數據。終端向服務器發起通信的流程大致如下:
??1.終端生成一個隨機密碼:symPassword.
??2.終端將這個隨機密碼使用非對稱加密加密,加密使用服務器對應的公鑰(publicKey)。asyEncrypt(symPassword,publicKey),并將這個加密后的結果發到服務器端。
??3.服務器端使用私鑰進行非對稱解密asyDecrypt(encryptedSymPassword,privateKey),解密得到symPassword.
??4.終端使用symEncrypt(data,symPassword)對data進行加密,并將加密結果發送到服務器。
??5.服務器使用symDecrypt(encryptedData,symPassword)對數據進行解密。
??這個方案使用臨時的對稱加密密碼來進行數據的加密傳輸,由于臨時密碼可以在每次通信建立時重新生成,所以不會有密碼泄露的風險。
??
??上文的加密通信還有個問題沒有解決,就是服務器的公鑰如何發放到眾多的終端。如果只是小范圍內使用,比如一個辦公室內部,可以用U盤將服務器公鑰拷貝到每個終端計算機上。但如果是一個公共網站,希望和全世界的所有用戶的通信都是安全的,該怎么發放服務器的公鑰呢?這將就要用到數字證書了。假定我們要為a.com的服務器發放一個證書,如下圖所示:
??
??終端訪問a.com時,先下載上圖右邊所示的數字證書。一般證書是從a.com下載,但從其它地方下載也是安全的,因為數字證書要驗證后才會使用。終端得到證書后,就開始驗證它,驗證步驟如下:
??1. 把上圖中證書下部的明文內容部分進行一次digest運算。
??2. 根據明文內容中證書簽發者的信息,在本機查找并驗證證書簽發者的公鑰。(稍后詳述這一過程)
??3. 用證書簽發者的公鑰,解密證書上部的數字簽名部分,使用asyDecrypt.
??4. 將第3步的asyDecrypt結果和第1步的digest結果進行比較,如果一樣,則認為證書合法;反之則說明證書非法或已損壞。
??5. 如果證書合法,就可以把明文內容中a.com的公鑰拿來使用了。
??前面步驟的第2步具體怎么操作的?注意到我們其實是要檢驗證書簽發者公鑰的合法性,我們就需要一個關于證書簽發者公鑰的證書:
??
??就這樣一環扣一環,形成了一個稱為證書鏈的東西。這樣的循環什么時候結束呢?一直找到一個值得信任的證書或根證書。根證書是證書擁有者自己給自己簽發的證書。根證書怎么驗證合法性?答案是不能,我們選擇信任它。我們為什么信任它,因為它是和操作系統或瀏覽器一起發布的。
??在實際應用中,證書還有個過期的概念。這也是由非對稱加密的特性3.2.2.決定的,為了防止經過較長時間的計算由某個簽發者的公鑰算出他對應的私鑰。
??
??這實際上是在HTTP協議的下層增加了由4.1和4.2組合成的加密通信協議。先有4.2得到網站的公鑰,再用4.1的方法傳輸HTTP數據。具體的實現不在本文討論的范圍。
??
??不外乎也是本文討論的三類算法的組合應用,將在接下來的文章討論這個話題。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。