?——秘密的精華
?在使用對稱密碼、公鑰密碼、消息認證碼、數字簽名等密碼技術使用,都需要壹個稱為 密鑰 的巨大數字。然而,數字本身的大小並不重要,重要的是 密鑰空間的大小 ,也就是可能出現的密鑰的總數量,因為密鑰空間越大,進行暴力破解就越困難。密鑰空間的大小是由 密鑰長度 決定的。
?對稱密碼DES的密鑰的實質長度為56比特(7個字節)。
例如,
壹個DES密鑰用二進制可以表示為:
01010001 11101100 01001011 00010010 00111101 01000010 00000011
用十六進制則可以表示為:
51 EC 4B 12 3D 42 03
而用十進制則可以表示為:
2305928028626269955
?在對稱密碼三重DES中,包括使用兩個DES密鑰的DES-EDE2和使用三個DES密鑰的DES-EDE3這兩種方式。
DES-EDE2的密鑰長度實質長度為112比特(14字節),比如:
51 EC 4B 12 3D 42 03 30 04 D8 98 95 93 3F
DES-EDE3的密鑰的實質長度為168比特(21字節),比如:
51 EC 4B 12 3D 42 03 30 04 D8 98 95 93 3F 24 9F 61 2A 2F D9 96
?對稱密碼AES的密鑰長度可以從128、192和256比特中進行選擇,當密鑰長度為256比特時,比如:
51 EC 4B 12 3D 42 03 30 04 D8 98 95 93 3F 24 9F 61 2A 2F D9 96
B9 42 DC FD A0 AE F4 5D 60 51 F1
? 密鑰和明文是等價的 。假設明文具有100萬的價值,那麽用來加密這段明文的密鑰也就是具有100萬元的價值;如果明文值1億元,密鑰也就值1億元;如果明文的內容是生死攸關的,那麽密鑰也同樣是生死攸關的。
?在對稱密碼中,加密和解密使用同壹個密鑰。由於發送者和接收者需要***享密鑰,因此對稱密碼又稱為***享密鑰密碼。對稱密碼中所使用的密鑰必須對發送者和接收者以外的人保密,否則第三方就能夠解密了。
?在消息認證碼中,發送者和接收者使用***享的密鑰來進行認證。消息認證碼只能由持有合法密鑰的人計算出來。將消息認證碼附加在通信報文後面,就可以識別通信內容是否被篡改或偽裝,由於“持有合法的密鑰”就是發送者和接收者合法身份的證明,因此消息認證碼的密鑰必須對發送者以外的人保密,否則就會產生篡改和偽裝的風險。
?在數字簽名中,簽名生成和驗證使用不同的密鑰,只有持有私鑰的本人才能夠生成簽名,但由於驗證簽名使用的是公鑰,因此任何人都能夠驗證簽名。
?對稱密碼和公鑰密碼的密鑰都是用於確保機密性的密鑰。如果不知道用於解密的合法密鑰,就無法得知明文的內容。
?相對地,消息認證碼和數字簽名所使用的密鑰,則是用於認證的密鑰。如果不知道合法的密鑰,就無法篡改數據,也無法偽裝本人的身份。
?當我們訪問以https://開頭的網頁時,Web服務器和瀏覽器之間會進行基於SSL/TLS的加密通信。在這樣的通信中所使用的密鑰是僅限於本次通信的壹次密鑰,下次通信時就不能使用了,想這樣每次通信只能使用壹次的密鑰稱為 會話密鑰 。
?由於會話密鑰只在本次通信中有效,萬壹竊聽者獲取了本次通信的會話密鑰,也只能破譯本次通信的內容。
?雖然每次通信都會更換會話密鑰,但如果用來生成密鑰的偽隨機數生成器品質不好,竊聽者就有可能預測出下次生成會話密鑰,這樣就會產生通信內容被破譯的風險。
?相對於每次通信更換的會話密鑰,壹直被重復使用的密鑰稱為 主密鑰 。
?壹般來說,加密的對象是用戶直接使用的信息,這樣的情況下所使用的密鑰稱為CEK(Contents Encryting Key,內容加密密鑰);相對地,用於加密密鑰的密鑰則稱為KEK(Key Encryting Key,密鑰加密密鑰)。
?在很多情況下,之前提到的會話密鑰都是被作為CEK使用的,而主密鑰則是被作為KEK使用的。
?生成密鑰的最好方法就是使用隨機數,因為米喲啊需要具備不易被他人推測的性質。在可能的情況下最好使用能夠生成密碼學上的隨機數的硬件設備,但壹般我們都是使用偽隨機數生成器這壹專門為密碼學用途設計的軟件。
?在生成密鑰時,不能自己隨便寫出壹些像“3F 23 52 28 E3....”這樣的數字。因為盡管妳想生成的是隨機的數字,但無論如何都無法避免人為偏差,而這就會成為攻擊者的目標。
?盡管生成偽隨機數的算法有很多種,但密碼學用途偽隨機生成器必須是專門針對密碼學用途而設計的。例如,有壹些偽隨機數生成器可以用於遊戲和模擬算法,盡管這些偽隨機數生成器所生成的數列看起也是隨機的,但只要不是專門為密碼學用途設計的,就不能用來生成密鑰,因為這些偽隨機數生成器不具備不可預測性這壹性質。
?有時候我們也會使用人類的可以記住的口令(pasword或passphrase)來生成密鑰。口令指的是壹種由多個單詞組成的較長的password。
?嚴格來說,我們很少直接使用口令來作為密鑰使用,壹般都是將口令輸入單向散列函數,然後將得到的散列值作為密鑰使用。
?在使用口令生成密鑰時,為了防止字典攻擊,需要在口令上附加壹串稱為鹽(salt)的隨機數,然後在將其輸入單向散列函數。這種方法稱為“基於口令的密碼(Password Based Encryption,PBE)”。
?在使用對稱密碼時,如何在發送者和接收者之間***享密鑰是壹個重要的問題,要解決密鑰配送問題,可以采用事先***享密鑰,使用密鑰分配中心,使用公鑰密碼等方法,除了上述方法,之前還提到壹種解決密鑰配送的問題的方法稱為Diffie-Hellman密鑰交換。
?有壹種提供通信機密性的技術稱為 密鑰更新 (key updating),這種方法就是在使用***享密鑰進行通信的過程中,定期更改密鑰。當然,發送者和接收者必須同時用同樣的方法來改變密鑰才行。
?在更新密鑰時,發送者和接收者使用單向散列函數計算當前密鑰的散列值,並將這個散列值用作新的密鑰。簡單說,就是 用當前密鑰散列值作為下壹個密鑰 。
?我們假設在通信過程中的某個時間點上,密鑰被竊聽者獲取了,那麽竊聽者就可以用這個密鑰將之後的通信內容全部解密。但是,竊聽者卻無法解密更新密鑰這個時間點之前的內容,因為這需要用單向散列函數的輸出反算出單向散列函數的輸入。由於單向散列函數具有單向性,因此就保證了這樣的反算是非常困難的。
?這種防止破譯過去的通信內容機制,稱為 後向安全 (backward security)。
?由於會話密鑰在通信過程中僅限於壹次,因此我們不需要保存這種秘密。然而,當密鑰需要重復使用時,就必須要考慮保存密鑰的問題了。
?人類是 無法記住具有實用長度的密鑰 的。例如,像下面這樣壹個AES的128比特的密鑰,壹般人是很難記住的。
51 EC 4B 12 3D 42 03 30 04 DB 98 95 93 3F 24 9F
就算勉強記住了,也只過不是記住壹個密鑰而已。但如果要記住多個像這樣的密鑰並且保證不忘記,實際上是非常困難的。
?我們記不住密鑰,但如果將密鑰保存下來又可能會被竊取。這真是壹個頭疼的問題。這個問題很難得到徹底解決,但我們可以考慮壹些合理的解決方法。
?將密鑰保存生文件,並將這個文件保存在保險櫃等安全地方。但是放在保險櫃裏的話,出門就無法使用了。這種情況,出門時就需要隨身攜帶密鑰。而如果將密鑰放在存儲卡隨身攜帶的話,就會產生存儲卡丟失、被盜等風險。
?萬壹密鑰被盜,為了能夠讓攻擊者花更多的時間才能真正使用這個密鑰,我們可以使用將密鑰加密後保存的方法,當然,要將密鑰加密,必須需要另壹個密鑰。像這樣用於密碼加密的密鑰,壹般稱為KEK。
?對密鑰進行加密的方法雖然沒有完全解決機密性的問題,但在現實中卻是壹個非常有效地方法,因為這樣做可以減少需要保管密鑰的數量。
?假設計算機上有100萬個文件,分別使用不同的密鑰進行加密生成100萬個密文,結果我們手上就產生了100萬個密鑰,而要保管100萬個密鑰是很困難的。
?於是,我們用壹個密鑰(KEK)將這100萬個密鑰進行加密,那麽現在我們只要保管者壹個KEK就可以了,這壹個KEK的價值相當於簽名的100萬個密鑰的價值的總和。
?用1個密鑰來代替多個密鑰進行保管的方法,和認證機構的層級化非常相似。在後者中,我們不需要信任多個認證機構,而只需要信任壹個根CA就可以了。同樣的,我們也不需要確保多個密鑰的機密性,而只需要確保壹個KEK的機密性就可以了。
?密鑰的作廢和生成是同等重要的,這是因為密鑰和明文是等價的。
?假設Alice向Bob發送了壹封加密郵件。Bob在解密之後閱讀了郵件的內容,這時本次通信所使用的密鑰對於Alice和Bob來說就不需要了。不在需要的密鑰必須妥善刪除,因為如果被竊聽者Eve獲取,之前發送的加密郵件就會被解密。
?如果密鑰是計算機上的壹個文件,那麽僅僅刪除這個文件是不足以刪除密鑰的,因為有壹些技術能夠讓刪除的文件“恢復”。此外,很多情況下文件的內容還會殘留在計算機的內存中,因此必須將這些痕跡完全抹去。簡而言之,要完全刪除密鑰,不但要用到密碼軟件,還需要在設計計算機系統時對信息安全進行充分的考慮
?如果包含密鑰的文件被誤刪或者保管密鑰的筆記本電腦損壞了,會怎麽樣?
?如果丟失了對稱密鑰密碼的***享密鑰,就無法解密密文了。如果丟失了消息認證碼的密鑰,就無法向通信對象證明自己的身份了。
?公鑰密碼中,壹般不太會發送丟失公鑰的情況,因為公鑰是完全公開的,很有可能在其他電腦上存在副本。
?最大的問題是丟失公鑰密碼的私鑰。如果丟失了公鑰密碼的私鑰,就無法解密用公鑰密碼加密的密文了。此外,如果丟失了數字簽名的私鑰,就無法生成數字簽名了。
?Diffie-Hellman密鑰交換(Diffie-Hellman key exchange)是1976年由Whitfield Diffie和Martin Hellman***同發明的壹種算法。使用這種算法,通信雙方僅通過交換壹些可以公開的信息就能夠生成***享秘密數字,而這壹秘密數字就可以被用作對稱密碼的密鑰。IPsec 中就使用了經過改良的Diffie-Hellman密鑰交換。
2 Alice 生成壹個隨機數A
?A是壹個1 ~ P-2之間的整數。這個數是壹個只有Alice知道的密碼數字,沒有必要告訴Bob,也不能讓Eve知道。
Alice計算出的密鑰=Bob計算出的密鑰
? 在步驟1-7中,雙方交換數字壹***有4個,P、G、G A mod P 和 G B mod P。根據這4個數字計算出Alice和Bob的***享密鑰是非常困難的。
?如果Eve能歐知道A和B的任意壹個數,那麽計算G A*B 就很容易了,然而僅僅根據上面的4個數字很難求出A和B的。
?根據G A mod P 計算出A的有效算法到現在還沒有出現,這問題成為有限域(finite field) 的 離散對數問題 。
?Diffie-Hellman密鑰交換是利用了“離散對數問題”的復雜度來實現密鑰的安全交換的,如果將“離散對數問題”改為“橢圓曲線上離散對數問題”,這樣的算法就稱為 橢圓曲線Diffie-Hellman 密鑰交換。
?橢圓曲線Diffie-Hellman密鑰交換在總體流程上是不變的,只是所利用的數學問題不同而已。橢圓曲線Diffie-Hellman密鑰交換能夠用較短的密鑰長度實現較高的安全性。
?基於口令密碼(password based encryption,PBE)就是壹種根據口令生成密鑰並用該密鑰進行加密的方法。其中加密和解密使用同壹個密鑰。
?PBE有很多種實現方法。例如RFC2898和RFC7292 等規範中所描述的PBE就通過Java的javax.crypto包等進行了實現。此外,在通過密碼軟件PGP保存密鑰時,也會使用PBE。
PBE的意義可以按照下面的邏輯來理解。
想確保重要消息的機制性。
?↓
將消息直接保存到磁盤上的話,可能被別人看到。
?↓
用密鑰(CEK)對消息進行加密吧。
?↓
但是這次又需要確保密鑰(CEK)的機密性了。
?↓
將密鑰(CEK)直接保存在磁盤上好像很危險。
?↓
用另壹個密鑰(KEK)對密鑰進行加密(CEK)吧。
?↓
等等!這次又需要確保密鑰(KEK)的機密性了。進入死循環了。
?↓
既然如此,那就用口令來生成密鑰(KEK)吧。
?↓
但只用口令容易遭到字典攻擊
?↓
那麽就用口令和鹽***同生成密鑰(KEK)吧。
?↓
鹽可以和加密後的密鑰(CEK)壹切保存在磁盤上,而密鑰(KEK)可以直接丟棄。
?↓
口令就記在自己的腦子裏吧。
PBE加密包括下列3個步驟:
? 鹽是由偽隨機數生成器生成的隨機數,在生成密鑰(KEK)時會和口令壹起被輸入單向散列函數。
?密鑰(KEK)是根據秘密的口令生成的,加鹽好像沒有什麽意義,那麽鹽到底起到什麽作用呢?
? 鹽是用來防禦字典攻擊的 。字典攻擊是壹種事先進行計算並準備好候選密鑰列表的方法。
?我們假設在生成KEK的時候沒有加鹽。那麽主動攻擊者Mallory就可以根據字典數據事先生成大量的候選KEK。
?在這裏,事先是很重要的壹點。這意味著Mallory可以在竊取到加密會話的密鑰之前,就準備好了大量的候選KEK。當Mallory竊取加密的會話密鑰後,就需要嘗試將它解密,這是準備好了大量事先生成的候選KEK,就能夠大幅度縮短嘗試的時間,這就是 字典攻擊 (dictionary attack)。
?如果在生成KEK時加鹽,則鹽的長度越大,候選KEK的數量也會隨之增大,事先生成的的候選KEK就會變得非常困難。只要Mallory還沒有得到鹽,就無法生成候選KEK。這是因為加鹽之後,候選KEK的數量會變得非常巨大。
?具有充足長度的密鑰是無法用人腦記憶的。口令也是壹樣,我們也無法記住具有充足比特數的口令。
?在PBE中,我們通過口令生成密鑰(KEK),在用這個密鑰來加密會話密鑰(CEK)。由於通過口令生成的密鑰(KEK)強度不如由偽隨機數生成器生成的會話密鑰(CEK),這就好像是將壹個牢固的保險櫃的鑰匙放在了壹個不怎麽牢固的保險櫃保管,因此在使用基於口令的密鑰時,需要將鹽和加密後的CEK通過物理方法進行保護。例如將鹽和加密後的CEK保存到存儲卡隨身攜帶。
?在生成KEK時,通過多次使用單向散列函數就可以提高安全性。例如,將鹽和口令輸入單向散列函數,進行1000次的散列函數所得到的散列值作為KEK來使用,是壹個不錯的方法。
?像這樣將單向散列函數進行多次叠代的方法稱為 拉伸 (stretching)。
該系列的主要內容來自《圖解密碼技術第三版》
我只是知識的搬運工
文章中的插圖來源於原著