觸碰密碼世界的大門
背景
前段時間有個文科朋友問我,能不能幫他拿到之前在他手機上登錄過的別人的密碼。我想了一下,用戶登錄的賬號密碼,如果保存在本地,不是應該加密過嗎?如果保存的是用戶第一次登錄伺服器返回的有時效性的token,這種情況肯定就拿不到明文密碼了。那麼本地保存的經過加密後的呢?或者,假定現在他是第一次登錄的請求呢?
鑒於現大多數登錄都是通過https,密碼也是經過SSL安全傳輸層加密處理後發送到服務端的。如果登錄使用的是http,登錄也應該是經過一些hash處理並且搭配圖形化的驗證碼或者驗證簡訊作為驗證,再配合後台的加密來保證一定程度的安全性的(介於竊聽者不需要原始密碼,通過hash結果等就可以偽造登錄,所以前端加密只能用來保護用戶的隱私,以防止被竊聽的原文密碼被用來社會學攻擊上,比如用戶多站點共享密碼,攻擊者竊聽到http網站下的原文密碼用在https的網站下)。接著我又想,那麼保存在本地的加密後的密碼呢,或者攻擊者直接處理加密後的密文呢?
以上只是我初步臆想,所以就有了進一步的學習,本來應該是了解關於網路安全的東西,但是偏偏就看了一下關於密碼學的東西(密碼學和網路安全是兩個方向),然後發現密碼學是一門深不可測但是很有意思的科學。下面給大家分享一下我收穫的一些簡單的知識。
一些密碼學基礎
先介紹一些密碼學的基礎知識
- 發送者和接收者: 發送者想要發送消息給接收者,並且這個消息是安全的(讓偷聽者不能閱讀這個消息)
- 消息和加密:消息被稱作
明文
。通過某種方法偽裝消息以隱藏它的內容的過程稱作加密
。被加密的消息被稱作密文
。相應的,把密文轉變成明文的過程叫作解密
。
- 演算法和密鑰:密碼演算法也叫
密碼
,是用於加密和解密的數學函數。如果演算法的保密性是針對於保持演算法的秘密,這種演算法稱為受限制演算法。按現在的標準,這種受限制演算法保密性已經遠遠不夠。現代密碼學使用秘鑰
來解決了這個問題。有些演算法使用兩個不同的密鑰,即加密密鑰和解密密鑰不同。這些演算法的安全性就是基於密鑰的安全性,而不是演算法細節的安全性,這就意味著演算法可以公開,即使偷聽者知道演算法,但是不知道具體使用的密鑰,就不可能閱讀消息。
- 密碼系統:由所有可能的明文、密文、密鑰、以及演算法組成。
- 對稱演算法:又叫傳統密碼演算法,加密秘鑰能從解密密鑰中推算出來,反過來也成立。通常加密和解密使用同一個密鑰,稱作
單密鑰演算法
或者是秘密密鑰演算法
。 - 公開密鑰演算法(非對稱演算法):用作加密的秘鑰不同於用作解密的解密秘鑰,而且解密秘鑰不能通過加密秘鑰計算出來(至少在合理假定的長時間內)。之所以叫作公開密鑰演算法,因為加密秘鑰能夠公開,但是偷聽者只能使用加密秘鑰加密信息,只有用相應的解密秘鑰才能解密信息。這裡,加密密鑰又被稱作
公開密鑰
(簡稱公鑰),解密秘鑰稱作私人密鑰
(簡稱私鑰)。 - 混合密碼系統:將對稱密碼和公鑰密碼結合起來的密碼方式稱為混合密碼系統。
- 密碼分析:密碼分析是在不知道密鑰的情況下,恢復出明文的科學。成功的密碼分析能恢復明文或者密鑰。也可以發現密碼體制的弱點而得到明文和密鑰。(密鑰通過非密碼分析的方式的丟失叫
泄露
) - 演算法的安全性:那麼什麼樣的演算法才是安全的呢?如果破譯演算法的代價大於加密數據的價值;如果破譯演算法所需要的時間比加密數據保密的時間更長;如果用單密鑰加密的數據量比破譯演算法需要的數據量少得多。那麼你可能是安全的。
歷史加密技術
單表加密
著名的愷撒密碼是一種簡單的替換密碼,它的每一個明文字元都是由其右邊第三個字元替換。它實際上是一種單表映射,數學上稱為單射
以英文字母26個為例
明碼錶:ABCDEFGHIJKLMNOPQRSTUVWXYZ
密碼錶:DEFGHIJKLMNOPQRSTUVWXYZABC
如果我們輸入HELLO WORLD,就會輸出KHOOR ZRUOG
這種密碼很好破解,密鑰最多也就26個,暴力破解法(窮舉法)手動都能找到
經過改版後的愷撒密碼使用隨機的密碼錶來使密鑰數大量增加,就不是使用移位了,有A26(26) = 26!種可能密鑰(手動暴力破解不是要試到猴年馬月)。但是有一種高端的學科叫概率論,頻率分析法
就是這種單表映射的剋星。拿到密文後,可以統計字母出現頻率,再對照英文字母頻率表來對照明文和密文的對應方式,這種方式需要交大的密文量,不然頻率分析就不準確了。
多表加密
代表為維吉尼亞密碼,是人們在單一愷撒密碼的基礎上擴展出的多表密碼。多表加密,顧名思義,就是多張換字表(單表)進行加密,這樣就可以消除字母出現的高頻率,頻率分析法也就失效了。
這張表叫做維熱納爾方陣,是為了方便加密者進行多字母替換而設計的。
例如,第一張表中「A」對應「B」,那我加密時第一次遇到「A」就要將其加密為「B」;第二張換字表中「A」對應「C」,那麼第二次遇見「A」,就加密為「C」,所以,如果我想加密「AA...」,那麼密文就會是「BC...」。當換字表用盡時進行下一輪循環。
維吉尼亞密碼用到了循環,所以實際上,維吉尼亞密碼就是有周期
的多組單表替代。既然存在周期,那麼就有被破譯的可能,如果觀察足夠多的密文,就會發現間隔多少位,會有規律地出現特定的字母組,比如of、the,找到了這些重複出現的字母組,那麼密鑰長度,可能就是他們的間距。具體破解的方法叫卡西斯基試驗
,感興趣的小夥伴可以去看看。
Enigma
既然單表不安全,多表也會被破解,那麼單表加多表的組合呢?
1918年,德國發明家亞瑟·謝爾比烏斯的發明了一個機器並給它起名叫做Enigma(迷)。按下機器鍵盤上的一個鍵,上方顯示器的一個母就會亮起來,同時在機器頂部的三個轉輪最右邊的那一個會相應轉動一個位置。再按下相同的鍵,另一個字母又會亮起來。
起初這台機器被用來加密商業機密,但是德國軍方看上了它,於是在整個二次世界大戰進程中,德軍使用Enigma作為加密通訊信息的工具。
這台機器看起來是一個裝滿了複雜而精緻的元件的盒子,雖然Enigma看上去挺複雜,但是拆分下來,它是由鍵盤(輸入字元)
,接線板
,轉輪
,反射器
,和顯示器
組成
- 鍵盤:加密字元的錄入
- 接線板:盒子最前面看到的那些插孔,操作員一般選6對字母插上交換線來改變字母對應關係,其他的字母不變,這相當於就是單表加密的作用,這裡就有
100391791500
種可能的替換表。 - 轉輪:轉輪是enigma的核心,一個enigma機一般裝了至少3個轉輪,操作員輸入一個字母,電流經過接線板進入第一個轉輪,經過轉子被置換成另一個字母(單個轉子對輸入內容所做的本質上是一次單字母替換加密),再相同地經過第二第三個轉輪到達反射器,經反射器再反向經過剛才經過的轉子到達顯示器。不同的是,每輸入一個字元,第一個轉輪就會轉動一格,當第一個轉輪轉到進位點時帶動第二個轉輪轉動,同理,當第二個轉輪轉動到進位點時帶動第三個轉輪轉動。轉輪在生產出來替換規則就定死了,也就是說,一個轉子提供26種不會改變的替換密碼錶,所以3個轉子就是263 =
17576
個不同密碼錶,再加上德軍一般是從5個轉輪中選擇3個並可以隨便排列位置,這又有C3(5) * A3(3) =60
種可能。(多表替換的表述決定密鑰長度,「卡西斯基試驗」在Enigma面前就沒有什麼用處了,17576的密鑰長度意味著密文至少要在17576位之後才會出現循環加密,一般哪裡有這麼長的密文) - 反射器:反射器和轉子一樣,區別在於
不會轉動
,而且替換規則是一對字母的替換
,比如輸入A,反射器替換成B,輸入B,反射器替換成A。這麼設計的作用是為了讓Enigma機能自我實現加密解密,可以類比光路可逆,電流流向也可逆,原理如下圖。
假如輸入A,電流流經3個轉輪被反射器反射回到三個轉輪輸出B,那麼我輸入B,就可以反向輸出A。
Enigma的操作員每個月都會收到一個密碼本,指定每天使用的密鑰,Enigma的密鑰如下:
- 三個轉子的排列順序(例如轉子從左至右編號分別為3-1-2)
- 三個轉子的轉動位置,這裡稱作指標組(例如轉子當前轉動到Z-Y-W)
- 接線板的設置(哪些字母兩兩交換)
以上就是Enigma機的原理,關於Enigma的破譯,最早破譯Enigma的是波蘭人,然後就是我們的計算機之父圖靈
最終破譯了Enigma,這段歷史感興趣的小夥伴可以自己搜搜。
這裡有一個在線Enigma的網站,可以去玩玩:http://enigmaco.de/enigma/enigma.html
在看到這裡時,因為一直都在學習,兩天沒敲代碼就手癢-0-,就想著自己用代碼實現一下Enigma機。
Enigma機的js實現
網上有很多實現enigma的代碼,但是大多數都太演算法化了,而且沒有注釋,比較難看懂,讀別人代碼尤其是沒有注釋的代碼是很痛苦的一件事。我按我的理解用代碼來還原enigma的整個系統,抽象出enigma機的各個部件,不對的地方還望指正。
我用數組來作為enigma內部字母表的替換,比如初始狀態為[A, B, C],我的映射表為[B, C, A],用兩數組相同index的項作為替換規則,那麼替換表結果就為 A => B、B => C。
首先是反射板,因為反射板字母的替換規則必須是兩兩交換,所以寫了一個shuffle函數來生成一個隨機的兩兩交換的反射板
/**n * 反射板n*/nclass Reflector {n constructor () {n // 反射板字母反射關係n this.mapping = [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, Sn , T, U, V, W, X, Y, Z]n }n // 隨機設置反射板映射關係 (兩兩交換)n shuffle (arr) {n let copyArr = arr.slice()n let map = {}n let resultList = []n let count = 0n while (copyArr.length > 0) {n if (map[arr[count]]) {n count++n continuen }n // 記錄處理過的字母n map[arr[count]] = truen copyArr.splice(copyArr.indexOf(arr[count]), 1) n let randSeq = Math.round(Math.random() * (copyArr.length - 1))n if (!map[copyArr[randSeq]]) {n // 隨機一個字母的位置n let index = arr.indexOf(copyArr[randSeq])n // 交換位置後放在對應位置上n resultList[count] = copyArr[randSeq]n resultList[index] = arr[count]n // 已換的位置作標記n map[copyArr[randSeq]] = truen // 刪除已經交換的字母n copyArr.splice(randSeq, 1)n count++n }n }n this.mapping = resultListn }n init () {n // 打亂字母 生成隨機的映射關係n this.shuffle(this.mapping)n }n}n
然後是轉子,我以數組第一位作為指標組
的位置,也是就當前轉子轉到哪裡了,然後生成一個隨機的進位點
,轉子的替換表規則不用兩兩交換,所以用了一個完全隨機的函數打亂數組元素,然後包括轉子的順時針和逆時針轉動。
/**n * 轉子 轉子指標組默認為數組第一個位置n*/nclass Roter extends Reflector {n constructor () {n super()n // 用於表示該轉子轉動到哪兒了n this.index = 0n // 進位 該轉子進位點n this.carry = 0n }n // 順時針旋n cwRote (distance) {n this.mapping = this.mapping.concat(this.mapping.splice(0, distance))n this.index += distancen while (this.index > 25) {n this.index -= 26n }n }n // 逆時針旋轉n acwRote (distance) {n let len = this.mapping.lengthn this.mapping = this.mapping.splice(len - distance, distance).concat(this.mapping)n this.index -= distancen while (this.index < 0) {n this.index = 26 + this.indexn }n }n // 字母亂序 完全隨機n shuffle (arr) {n let len = arr.length;n for (let i = 0; i < len - 1; i++) {n let idx = Math.floor(Math.random() * (len - i))n let temp = arr[idx]n arr[idx] = arr[len - i - 1]n arr[len - i - 1] = tempn }n return arrn }n init () {n // 打亂字母 生成隨機的映射關係n this.shuffle(this.mapping)n // 生成 隨機進位點n this.carry = Math.round(Math.random() * 25)n }n}n
接下來是接線板,接線板因為是需要接線員手動選擇替換情況的,所以傳入一個替換規則
/**n * 接線板n*/nclass Plug {n constructor() {n this.mapping = [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, Sn , T, U, V, W, X, Y, Z]n }n /**n * 設置接線板 字母交換情況:A和B交換 C和D交換n * 交換的數組 [[A, B], [C, D]]n */n init (changeArr) {n changeArr.map(item => {n if (item[0] === item[1]) {n returnn }n let frontIdx = this.mapping.indexOf(item[0])n let nextIdx = this.mapping.indexOf(item[1])n let middle = this.mapping[nextIdx]n this.mapping[nextIdx] = this.mapping[frontIdx]n this.mapping[frontIdx] = middlen })n }n}n
好,現在零件都齊了,就剩最後組合出Enigma機了。首先是sortRoter函數,用來設置轉子的排列順序,接著是setRoterIndex函數,用來設置轉子的轉動情況。關鍵在於inputChar 字元錄入函數,為了便於理解,用了current變數也就是數組當前索引來模擬電流流向,input作為一個零件的輸入,多寫了一個output變數作為一個零件的輸出(一個零件的輸出是另一個零件的輸入),有點冗餘,但是能清晰模擬電流方向。這樣,電流經: 輸入 ==> 接線板 ==> 第一個轉子 ==> 第二個轉子 ==> 第三個轉子 ==> 反射器 ==> 第三個轉子 ==> 第二個轉子 ==> 第一個轉子 ==> 輸出。這樣就很容易理解了。
/**n * 英格瑪機抽象類n*/nclass Enigma {n constructor () {n this.reflector = new Reflector()n this.plug = new Plug()n this.roterArr = [new Roter(), new Roter(), new Roter()]n }n /*n *設置接線板 字母交換情況n * @changeArr [[A, C]] 接線板轉換情況n */n init (changeArr) {n if (Object.prototype.toString.call(changeArr) !== [object Array]) {n returnn }n this.reflector.init()n this.plug.init(changeArr)n this.roterArr.map(item => {n item.init()n })n }n /**n * 設置轉子排列順序n * [0, 1, 2] [2, 0, 1] 轉子排列n */n sortRoter (sort) {n let first = this.roterArr[sort[0]]n let second = this.roterArr[sort[1]]n let third = this.roterArr[sort[2]]n this.roterArr = [first, second, third]n }n /**n * 設置轉子 指標 轉子指標組當前轉到哪個位置n * @arr [A, B, C]n * */ n setRoterIndex (arr) {n if (Object.prototype.toString.call(arr) !== [object Array]) {n returnn }n // 轉動轉子到指標所在位置n let first = Math.abs(this.roterArr[0].mapping.indexOf(arr[0]))n this.roterArr[0].cwRote(first)nn let second = Math.abs(this.roterArr[1].mapping.indexOf(arr[1]))n this.roterArr[1].cwRote(second)nn let third = Math.abs(this.roterArr[2].mapping.indexOf(arr[2]))n this.roterArr[2].cwRote(third)n }n inputChar (char) {n // 處理映射關係的數組n let startArr = [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, Sn , T, U, V, W, X, Y, Z]n let input = charn let outputn // 當前電流位置n let current = startArr.indexOf(input)nn // 經過接線板n output = this.plug.mapping[current]n input = outputn current = startArr.indexOf(input)nn // 經過第一個轉輪n output = this.roterArr[0].mapping[current]n input = outputn current = startArr.indexOf(input)nn // 經過第二個轉輪n output = this.roterArr[1].mapping[current]n input = outputn current = startArr.indexOf(input)nn // 經過第三個轉輪n output = this.roterArr[2].mapping[current]nnn // 此時倒推回去 n // 經過反射器n input = outputn current = this.reflector.mapping.indexOf(input)n output = startArr[current]nn // 經過第三個轉輪n input = outputn current = this.roterArr[2].mapping.indexOf(input)n output = startArr[current]nn // 經過第二個轉輪n input = outputn current = this.roterArr[1].mapping.indexOf(input)n output = startArr[current]nn // 經過第一個轉輪n input = outputn current = this.roterArr[0].mapping.indexOf(input)n output = startArr[current]nn // 經過接線板n input = outputn current = this.plug.mapping.indexOf(input)n output = startArr[current]nn // 第一個轉子順時針轉動1格n this.roterArr[0].cwRote(1)n // 第一個轉子轉到進位點n if (this.roterArr[0].index == this.roterArr[0].carry) {n // 第二個轉子逆時針轉動1格n this.roterArr[1].acwRote(1)n }n // 第二個轉子轉到進位點n if (this.roterArr[1].index == this.roterArr[1].carry) {n // 第三個轉子順時針轉動1格n this.roterArr[2].cwRote(1)n }nn return output n }n}n
以上是我實現的Enigma加密器,首先初始化enigma機,然後初始化接線板接線規則,調整轉子排列順序,調整轉子位置,然後就可以單字元輸入,經過一系替換後輸出加密後的字元了。在相同的轉子排列和轉子位置下,輸入加密後的字元,就可以輸出剛才的明文字元。
現代加密技術
在計算機出現以前,密碼學由基於字元的密碼組成。不同的密碼演算法是字元之間互相替換或者互相換位,好的密碼是結合這兩種方法進行多次運算。而現代的變化是演算法對比特而不是對字母進行變換,實際上只是字母表的改變,從26個字元變成2個字元,好的演算法仍然是代替和換位的組合。
Kerckhoff加密原則:一個安全保護系統的安全性不是建立在它的演算法對於對手來說是保密的,而是應該建立在它所選擇的密鑰對於對手來說是保密的,這一原則現也被普遍承認為傳統密碼與現代密碼的分界線。
對稱演算法
最開始提到的,演算法在加密和解密時使用相同的密鑰,或是使用兩個可以簡單地相互推算的密鑰。
- DES(Data Encryption Standard):DES是現代密碼的第一個標誌,它在1977年被美國政府正式採納為數據加密的標準,然而隨著計算機進步,DES已經能被暴力破解了,強度大不如從前。
- 3DES(Triple DES):DES的升級版,為了增強DES的強度,將DES重複3次得到的一種密碼演算法。
- AES(Advanced Encryption Standard):是取代前任(DES)而成為新標準的一種對稱演算法,它的原型是一種名為Rijndael的對稱密碼演算法,於2000年全世界若干候選對稱演算法中脫穎而出被選為新一代的標準密碼演算法---AES。
公開密鑰演算法(非對稱演算法)
在對稱密碼中,因為加密和解密使用的相同的密鑰,所以必須向接收者配送密鑰。公鑰密碼技術就是解決密鑰的配送問題而產生的----兩把鑰匙,用公鑰加密
,用私鑰解密
我們來認識兩個密碼學上的知名人士Alice和Bob,現在他們是一對地下情侶,以及一個自作多情的第三者Eve。
Alice和Bob想互相寫情書,但是他們不想讓Eve偷看到他們互遞情書內容,於是他們準備給情書加密。Alice加密後,把情書給Bob看,但是情書已經加密了,Bob看不懂,Alice意識到她還得把解密的密鑰給一起發送給Bob。
但是如果Alice直接把密文和密鑰一起發送給Bob行不行呢?如果一起發送,Eve兩個都會拿到就可以像Bob一樣看情書的內容了,也就是說,同時發送密鑰,Eve也能完成解密。Alice一籌莫展,密鑰必須發送給Bob,但又不能發送,哎呀她要糾結死了。
後來,Alice想到,既然必須給鑰匙,那麼我可以準備兩把鑰匙啊,於是她和Bob商量這麼做:
1)兩人準備兩把配對鑰匙,一把用來加密(公鑰),一把用來解密(私鑰)。
2)Bob把他的公鑰發送給Alice,這時被Eve截獲,Eve很興奮,「嗨呀,拿到你們的鑰匙了」
3)然後Alice收到Bob的公鑰後,用Bob的公鑰加密,然後把密文發送給Bob。這時又被Eve截獲,「嗨呀,看我破解你的密碼,咦?怎麼打不開呢?」
4)Bob拿到Alice給他的密文後,用自己的私鑰對密文解密。(從此以後,Alice和Bob的地下戀情就不怕被Eve曝光了,我們只是在談論學習,你是不會懂的。Eve還是一臉懵逼)
以上就是公鑰密碼在傳輸過程中的原理。
常見非對稱演算法有:
- DSA(Digital Signature Algorithm):數字簽名演算法,是一種標準的 DSS(數字簽名標準)
- ECC(Elliptic Curves Cryptography):橢圓曲線密碼,它是通過將橢圓曲線上的特定點進行特殊的乘法運算實現的,它利用了這種乘法運算的逆運算非常困難的特徵。
- RSA(以三個開發者命名:Rivet、Shamir、Adelman):現在使用最廣泛的公鑰密碼演算法,SSL的密碼系統中就用到了它。
證書
Alice和Bob的生活過得美滋滋,但是Eve很生氣,Eve破解不了他們的加密的密碼,「哼,沒關係」。
1)Alice又在問Bob要公鑰了,Bob收到命令後,把自己的公鑰發送給Alice,這時又被Eve拿到了,Eve這次不給Alice了,它把Bob的公鑰藏了起來,並且把自己的公鑰發給Alice。
2)Alice拿到了鑰匙,但是它以為這就是Bob的鑰匙,於是寫上「我愛你」,然後用這個公鑰加密後發給Bob。
3)又被Eve攔截了,因為Alice使用的是它的公鑰,所以Eve用自己的私鑰打開,看到了「我愛你」,「哇,原來你們在我背後搞這些事情,我要拆散你們!」於是Eve寫上,「你這個丑鬼,我再也不想見到你了」然後用剛才藏起來的Bob的公鑰加密,發給Bob。
4) Bob心都碎了,重複上述,Eve也可以隨意篡改Bob發給Alice的消息了。於是,兩人分手了,嘿嘿嘿~
以上是公鑰密碼演算法潛在的問題,中間人攻擊
,但是這種攻擊並不針對演算法本身。公鑰密碼並沒有被破譯,密碼演算法正常工作並保證了機密性,但是機密性只是在Alice和Eve,Eve和Bob之間的。所以,僅僅靠公鑰密碼本身,無法防禦中間人攻擊。
所以問題的起因就是不能判斷公鑰的由來,於是就有了公鑰證書
。公鑰證書簡稱證書
,和身份證相似,裡面有各種個人所屬信息,以及屬於個人的公鑰,並有認證機構
(CA)施加數字簽名
。認證機構中有國際性組織和政府設立的組織,也有通過認證服務盈利的企業。這樣相當於公鑰就有了身份證,身份證該可以證明來源真實性了吧。
數字簽名
數字簽名就是現實社會中籤名或者蓋章這樣的行為數字世界的實現,數字簽名的處理過程耗時,一般不會對整個消息做數字簽名,而是先通過單項散列函數
計算出消息的散列值,再對這個散列值做數字簽名。
其中單項散列函數一般用於驗證消息的完整性
,我們經常做的登錄驗證實際上就是單項散列函數的一種應用,它能根據任意長度的消息計算出固定長度的散列值,通過對比散列值就可以判斷兩條消息是否一致。但是,單項散列函數能辨別出「篡改」
,但無法辨別「偽裝」
。還需要上述的認證
。
常見的單項散列函數有:
- MD4:Rivest於1990年設計的單項散列函數,不過隨著Dobbertin提出尋找散列碰撞的方法,因此它現在已經不安全了。
- MD5:我們常見的MD5,是由Rivest於1991年設計的,它的強抗碰撞性也已經被攻破,因此也不安全了。
- SHA-1、SHA-256、SHA-384、SHA-512:由NIST(美國國家標準技術研究所)設計的單項散列函數,其中,SHA-1的強抗碰撞性已於2005年被攻破。SHA-256、SHA-384、SHA-512統稱為SHA-2。
混合密碼演算法
使用對稱密碼,可以保證機密性,但是需要解決密鑰配送問題;使用公鑰密碼,處理速度遠遠低於對稱密碼外,還難以防禦中間人攻擊。所以就有了混合密碼系統---將對稱密碼和公鑰密碼相結合的方法。
用快速的對稱密碼對消息加密,消息轉換成了密文,保證了消息的機密性
。然後用公鑰密碼對對稱密碼的密鑰進行加密,由於對稱密碼的密鑰一般比信息短,所以公鑰密碼的速度慢的問題就可以被忽略了,這樣就保證了密鑰配送的安全性
。
混合密碼系統還用了偽隨機數生成器
生成對稱密碼加密中使用的會話密鑰,結合這三種技術創造出了兼具兩者優點的密碼方式。著名密碼軟體PGP
,以及我們眾所周知的SSL/TLS
都運用的是混合密碼系統。
結語
本來想再仔細研究現代加密演算法的具體實現,但是發現自己大腦已經發燒,這次就先到這裡,雖然自己還在密碼世界的大門之外,但是也略有所獲,我先去買瓶六個核桃。
推薦閱讀:
※如果你也擔心密碼泄露,請看下這份秘籍。
※洋蔥吳洪聲:「奶罩」哥如何罩住賬號安全?
※如何保護好你的數字身份
※溶液筆+透明膠帶可以解鎖帶指紋密碼手機?是什麼原理?
※沒有這個顏值爆表的博士,你們還過什麼1024?!