前言
開發網站登入功能時,如何保證密碼在傳輸過程/儲存的安全?
相信不少前後端的朋友,在面試時都會被問到類似的問題。
在我對密碼學一無所知時,也僅會回答:“MD5
加密啊。”
諸不知,密碼學在網路七層模型,甚至web
開發中的應用比我想象得多得多。
1. 什麼是密碼學?
密碼學是各種安全應用程式所必需的,現代密碼學旨在建立通過應用數學原理和電腦科學來保護資訊的機制。但相比之下,密碼分析旨在解密此類機制,以便獲得對資訊的非法訪問。
密碼學具有三個關鍵屬性:- 機密性,為了防止未經授權的各方訪問資訊(換句話說,是要確保只有經過授權的人才能訪問受限制的資料)。
- 完整性,是指保護資訊不被隨意篡改
- 真實性,與識別資訊的所有者有關。
例如個人醫療資料:
- 機密性,個人醫療資料需要保密,這意味著只有醫生或醫護人員才能訪問它。
- 完整性,還必須保護其完整性,因為篡改此類資料可能導致錯誤的診斷或治療,並給患者帶來健康風險。
- 真實性,患者資料應與已識別的個人聯絡起來,且患者需要知道操作者(醫生)是誰。
在本文中,我們將從加密,雜湊,編碼和混淆四種密碼學基礎技術來入門。
本文圖片經過再製,方便看懂。
大綱和主體內容引自: How Secure Are Encryption, Hashing, Encoding and Obfuscation?
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)}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
。
後記 & 引用
那麼,如何保證密碼在傳輸過程/儲存的安全呢?
我們下篇再見!❤️ 看完三件事
如果你覺得這篇內容對你挺有啟發,我想邀請你幫我三個小忙:
- 點贊,讓更多的人也能看到這篇內容(收藏不點贊,都是耍流氓 -_-)
- 關注公眾號「前端勸退師」,不定期分享原創知識。
- 也看看其它文章
- Chrome Devtools 高階除錯指南(新)
- JavaScript 工具函式大全(新)
- 「React Hooks」120行程式碼實現一個互動完整的拖拽上傳元件
- 「React Hooks」160行程式碼實現動態炫酷的視覺化圖表 - 排行榜
也可以來我的GitHub
部落格裡拿所有文章的原始檔:
前端勸退指南:github.com/roger-hiro/…