一文搞懂Web中暗藏的密碼學
前言
開發網站登錄功能時,如何保證密碼在傳輸過程/儲存的安全?
相信不少前后端的朋友,在面試時都會被問到類似的問題。
在我對密碼學一無所知時,也僅會回答:“MD5加密啊。”
諸不知,密碼學在網絡七層模型,甚至web開發中的應用比我想象得多得多。
1. 什么是密碼學?
密碼學是各種安全應用程序所必需的,現代密碼學旨在創建通過應用數學原理和計算機科學來保護信息的機制。但相比之下,密碼分析旨在解密此類機制,以便獲得對信息的非法訪問。
密碼學具有三個關鍵屬性:
- 機密性,為了防止未經授權的各方訪問信息(換句話說,是要確保只有經過授權的人才能訪問受限制的數據)。
- 完整性,是指保護信息不被隨意篡改
- 真實性,與識別信息的所有者有關。
例如個人醫療數據:
- 機密性,個人醫療數據需要保密,這意味著只有醫生或醫護人員才能訪問它。
- 完整性,還必須保護其完整性,因為篡改此類數據可能導致錯誤的診斷或治療,并給患者帶來健康風險。
- 真實性,患者數據應與已識別的個人聯系起來,且患者需要知道操作者(醫生)是誰。
在本文中,我們將從加密,哈希,編碼和混淆四種密碼學基礎技術來入門。
2. 什么是加密?
加密定義:以保證機密性的方式轉換數據的過程。
為此,加密需要使用一個保密工具,就密碼學而言,我們稱其為“密鑰”。
加密密鑰和任何其他加密密鑰應具有一些屬性:
- 為了保護機密性,密鑰的值應難以猜測。
- 應該在單個上下文中使用它,避免在不同上下文中重復使用(類比 JS 作用域)。密鑰重用會帶來安全風險,如果規避了其機密性,則影響更大,因為它“解鎖”了更敏感的數據。
2.1 加密的分類:對稱和非對稱
加密分為兩類:對稱和非對稱
對稱加密:
用途:文件系統加密,Wi-Fi 保護訪問(WPA),數據庫加密(例如信用卡詳細信息)
非對稱加密:
用途:TLS,VPN,SSH。
其主要區別是:所需的密鑰數量:
- 在對稱加密算法中,單個密用于加密和解密數據。只有那些有權訪問數據的人才能擁有單個共享密鑰。
- 在非對稱加密算法中,使用了兩個密鑰:一個是公用密鑰,一個是私有密鑰。顧名思義,私鑰必須保密,而每個人都可以知道公鑰。
- 應用加密時,將使用公鑰,而解密則需要私鑰。
- 任何人都應該能夠向我們發送加密數據,但是只有我們才能夠解密和讀取它。
- 通常使用非對稱加密來在不安全的通道上進行通信時,兩方之間會安全地建立公共密鑰。
- 通過此共享密鑰,雙方切換到對稱加密。
- 這種加密速度更快,更適合處理大量數據。
能被密碼界承認的加密算法都是公開的:
- 某些公司使用專有或“軍事級”加密技術進行加密,這些技術是“私有的”。且基于“復雜“算法,但這不是加密的工作方式。
- 密碼界廣泛使用和認可的所有加密算法都是公開的,因為它們基于數學算法,只有擁有密鑰或先進的計算能力才能解決。
- 公開算法是得到廣泛采用,證明了其價值的。
3. 什么是哈希?
哈希算法定義:·一種只能加密,不能解密的密碼學算法,可以將任意長度的信息轉換成一段固定長度的字符串。
加密算法是可逆的(使用密鑰),并且可以提供機密性(某些較新的加密算法也可以提供真實性),而哈希算法是不可逆的,并且可以提供完整性,以證明未修改特定數據。
哈希算法的前提很簡單:給定任意長度的輸入,輸出特定長度的字節。在大多數情況下,此字節序列對于該輸入將是唯一的,并且不會給出輸入是什么的指示。換一種說法:
- 僅憑哈希算法的輸出,是無法確定原始數據的。
- 取一些任意數據以及使用哈希算法輸出,就可以驗證此數據是否與原始輸入數據匹配,從而無需查看原始數據。
為了說明這一點,請想象一個強大的哈希算法通過將每個唯一輸入放在其自己的存儲桶中而起作用。當我們要檢查兩個輸入是否相同時,我們可以簡單地檢查它們是否在同一存儲桶中。
散列文件的存儲單位稱為桶(Bucket)
3.1 例子一:資源下載
提供文件下載的網站通常會返回每個文件的哈希值,以便用戶可以驗證其下載副本的完整性。
例如,在Debian的圖像下載服務中,您會找到其他文件,例如SHA256SUMS,其中包含可供下載的每個文件的哈希輸出(在本例中為SHA-256算法)。
- 下載文件后,可以將其傳遞給選定的哈希算法,輸出一段哈希值
- 用該哈希值來與校驗和文件中列出的哈希值作匹配,以校驗是否一致。
在終端中,可以用openssl來對文件進行哈希處理:
- $ openssl sha256 /Users/hiro/Downloads/非對稱.png
- SHA256(/Users/hiro/Downloads/非對稱.png)= 7c264efc9ea7d0431e7281286949ec4c558205f690c0df601ff98d59fc3f4f64
同一個文件采用相同的hash算法時,就可以用來校驗是否同源。
在強大的哈希算法中,如果有兩個不同的輸入,則幾乎不可能獲得相同的輸出。
而相反的,如果計算后的結果范圍有限,就會存在不同的數據經過計算后得到的值相同,這就是哈希沖突。(兩個不同的數據計算后的結果一樣)
這種稱為:哈希碰撞(哈希沖突)。
如果兩個不同的輸入最終出現在同一個存儲桶中,則會發生沖突。如MD5和SHA-1,就會出現這種情況。這是有問題的,因為我們無法區分哪個碰撞的值匹配輸入。
強大的哈希算法幾乎會為每個唯一輸入創建一個新存儲桶。
3.2 例子二:網站登陸
在web開發中,哈希算法使用最頻繁的是在網站登陸應用上:
絕大多數的網站,在將登陸數據存入時,都會將密碼哈希后存儲。
- 這是為了避免他人盜取數據庫信息后,還原出你的初始輸入。
- 且下次登錄時,Web 應用程序將再次對你的密碼進行哈希處理,并將此哈希與之前存儲的哈希進行比較。
- 如果哈希匹配,即使 Web 應用程序中沒有實際的密碼存儲,Web 應用程序也確信你知道密碼。
注冊:
登陸:
哈希算法的一個有趣的方面是:無論輸入數據的長度如何,散列的輸出始終是相同的長度。
從理論上講,碰撞沖突將始終在可能性的范圍之內,盡管可能性很小。
與之相反的是編碼。
4. 什么是編碼?
編碼定義:將數據從一種形式轉換為另一種形式的過程,與加密無關。
它不保證機密性,完整性和真實性這三種加密屬性,因為:
- 不涉及任何秘密且是完全可逆的。
- 通常會輸出與輸入值成比例的數據量,并且始終是該輸入的唯一值。
- 編碼方法被認為是公共的,普遍用于數據處理。
- 編碼永遠不適用于操作安全性相關。
4.1 URL編碼
又叫百分號編碼,是統一資源定位(URL)編碼方式。URL地址(常說網址)規定了:
- 常用的數字,字母可以直接使用,另外一批作為特殊用戶字符也可以直接用(/,:@等)
- 剩下的其它所有字符必須通過%xx編碼處理。
現在已經成為一種規范了,基本所有程序語言都有這種編碼,如:
- js:encodeURI、encodeURIComponent
- PHP:urlencode、urldecode 等。
編碼方法很簡單,在該字節ascii碼的 16 進制字符前面加%. 如 空格字符,ascii碼是 32,對應 16 進制是'20',那么urlencode編碼結果是:%20。
- # 源文本:
- The quick brown fox jumps over the lazy dog
- # 編碼后:
- #!shell
- %54%68%65%20%71%75%69%63%6b%20%62%72%6f%77%6e%20%66%6f%78%20%6a%75%6d%70%73%20%6f%76%65%72%20%74%68%65%20%6c%61%7a%79%20%64%6f%67
4.2 HTML實體編碼
在HTML中,需要對數據進行HTML編碼以遵守所需的HTML字符格式。轉義避免 XSS 攻擊也是如此。
4.3 Base64/32/16編碼
base64、base32、base16可以分別編碼轉化 8 位字節為 6 位、5 位、4 位。
16,32,64 分別表示用多少個字符來編碼,
Base64常用于在通常處理文本數據的場合,表示、傳輸、存儲一些二進制數據。包括MIME的email,email via MIME,在XML中存儲復雜數據。
編碼原理:
Base64編碼要求把 3 個 8 位字節轉化為 4 個 6 位的字節
之后在 6 位的前面補兩個 0,形成 8 位一個字節的形式
6 位 2 進制能表示的最大數是 2 的 6 次方是 64,這也是為什么是 64 個字符的原因
A-Z,a-z,0-9,+,/這 64 個編碼字符,=號不屬于編碼字符,而是填充字符
Base64映射表,如下:
舉個栗子:
- 第一步:“M”、“a”、"n"對應的ASCII碼值分別為 77,97,110,對應的二進制值是01001101、01100001、01101110。如圖第二三行所示,由此組成一個 24 位的二進制字符串。
- 第二步:如圖紅色框,將 24 位每 6 位二進制位一組分成四組。
- 第三步:在上面每一組前面補兩個 0,擴展成 32 個二進制位,此時變為四個字節:00010011、00010110、00000101、00101110。分別對應的值(Base64編碼索引)為:19、22、5、46。
- 第四步:用上面的值在 Base64 編碼表中進行查找,分別對應:T、W、F、u。因此“Man”Base64編碼之后就變為:TWFu。
上面的示例旨在指出,編碼的用例僅是數據處理,而不為編碼的數據提供保護。
4. 什么是混淆?
混淆定義:將人類可讀的字符串轉換為難以理解的字符串。
- 與加密相反,混淆處理不包含加密密鑰。
- 與編碼類似,混淆不能保證任何安全性,盡管有時會誤將其用作加密方法
盡管不能保證機密性,但混淆仍有其它應用:
- 用于防止篡改和保護知識產權。
- APP 源代碼通常在打包之前就被混淆了
- 因為源代碼位于用戶的設備中,可以從中提取代碼。由于混淆后代碼不友好,因此會阻止逆向工程,從而有助于保護知識產權。
- 反過來,這可以防止篡改代碼并將其重新分發以供惡意使用。
但是,如此存在許多有助于消除應用程序代碼混淆的工具。那就是其它話題了。。。
4.1 例子一:JavaScript混淆
JavaScript源代碼:
- function hello(name) {
- console.log('Hello, ' + name);
- }
- hello('New user');
混淆后:
- var _0xa1cc=["\x48\x65\x6C\x6C\x6F\x2C\x20","\x6C\x6F\x67","\x4E\x65\x77\x20\x75\x73\x65\x72"];
- function hello(_0x2cc8x2){console[_0xa1cc[1]](_0xa1cc[0]+ _0x2cc8x2 "_0xa1cc[1]")}hello(_0xa1cc[2])
總結
從機密性,完整性,真實性分析四種密碼技術:
- 加密,雖然是為了保證數據的機密性,但某些現代加密算法還采用了其他策略來保證數據的完整性(有時通過嵌入式哈希算法)和真實性。
- 哈希,只能保證完整性,但可以通過完整性對比來做權限控制,如:基于哈希的消息認證碼(HMAC)和某些傳輸層安全性(TLS)方法。
- 編碼,過去曾被用來表示加密,并在技術領域之外仍具有這種含義,但在編程世界中,它僅是一種數據處理機制,從未提供任何安全措施。
- 混淆,可以用來提高抵御攻擊的能力;但是,它永遠不能保證數據的機密性。狡猾的對手最終將繞過混淆策略。與編碼一樣,永遠不要將混淆視為可靠的安全控制。
附錄:哈希函數常用的哈希函數:
- MD5,一種被廣泛使用的密碼雜湊函數,可以產生出一個 128 位元(16 位元組)的哈希值,用于確保信息傳輸完整一致。*雖廣泛,但過時。
- SHA-256/SHA512 , "加鹽"。在比特幣中,區塊鏈使用SHA-256算法作為基礎的加密哈希函數。
- 安全散列算法secure hash algorithm,是一個密碼哈希函數家族。
- SHA家族有五個算法,分別是SHA-1,SHA-224,SHA-256,SHA-384,SHA-512
- 它們是美國的政府標準,后面的四個稱之為SHA-2
- bcrypt:bcrypt算法相對來說是運算比較慢的算法。
在密碼學界有句常話:越慢的算法越安全。算法越算,黑客破解成本越高:
通過salt和const這兩個值來減緩加密過程,ta 的加密時間(百 ms 級)遠遠超過md5(大概1ms左右)。
對于計算機來說,Bcrypt 的計算速度很慢,但是對于用戶來說,這個過程不算慢。
bcrypt是單向的,而且經過salt和cost的處理,使其受rainbow攻擊破解的概率大大降低,同時破解的難度也提升不少。
相對于MD5等加密方式更加安全,而且使用也比較簡單.
- 設計良好的密鑰擴展算法,如PBKDF2,bcrypt,scrypt。
后記 & 引用
- How Secure Are Encryption, Hashing, Encoding and Obfuscation?[3]
- CTF 中那些腦洞大開的編碼和加密[4]
- 散列文件的存儲——‘桶’[5]
那么,如何保證密碼在傳輸過程/儲存的安全呢?
參考資料
How Secure Are Encryption, Hashing, Encoding and Obfuscation?: https://auth0.com/blog/how-secure-are-encryption-hashing-encoding-and-obfuscation/#What-is-Encoding-
引自:一篇文章徹底弄懂Base64編碼原理: https://blog.csdn.net/wo541075754/article/details/81734770
How Secure Are Encryption, Hashing, Encoding and Obfuscation?: https://auth0.com/blog/how-secure-are-encryption-hashing-encoding-and-obfuscation/#What-is-Encoding-
CTF中那些腦洞大開的編碼和加密: https://www.cnblogs.com/godoforange/articles/10850493.html
散列文件的存儲——‘桶’: https://blog.csdn.net/Dearye_1/article/details/78492021











































