前言
本系列最開始是為了自己面試準備的.後來發現整理越來越多,差不多有十二萬字元,最後決定還是分享出來給大家.
為了分享整理出來,花費了自己大量的時間,起碼是隻自己用的三倍時間.如果喜歡的話,歡迎收藏,關注我!謝謝!
文章連結
- 前端面試查漏補缺--(一) 防抖和節流
- 前端面試查漏補缺--(二) 垃圾回收機制
- 前端面試查漏補缺--(三) 跨域及常見解決辦法
- 前端面試查漏補缺--(四) 前端本地儲存
- 前端面試查漏補缺--(五) 渲染機制及重繪和迴流
- 前端面試查漏補缺--(六) 瀏覽器快取
- 前端面試查漏補缺--(七) XSS攻擊與CSRF攻擊
- 前端面試查漏補缺--(八) 前端加密
- 前端面試查漏補缺--(九) HTTP與HTTPS
- 前端面試查漏補缺--(十) 前端鑑權
- 前端面試查漏補缺--(十一) 前端軟體架構模式MVC/MVP/MVVM
- 前端面試查漏補缺--(十二) 從輸入URL到看到頁面發生的全過程(含三握手,四揮手詳解)
- 前端面試查漏補缺--(十三) 記憶體洩漏
- 前端面試查漏補缺--(十四) 演算法及排序
- 前端面試查漏補缺--(十五) Event Loop
合集篇:
前端面試查漏補缺--Index篇(12萬字元合集) 包含目前已寫好的系列其他十幾篇文章.後續新增值文章不會再在每篇新增連結,強烈建議議點贊,關注合集篇!!!!,謝謝!~
後續更新計劃
後續還會繼續新增設計模式,前端工程化,專案流程,部署,閉環,vue常考知識點 等內容.如果覺得內容不錯的話歡迎收藏,關注我!謝謝!
求一份內推
目前本人也在準備跳槽,希望各位大佬和HR小姐姐可以內推一份靠譜的武漢 前端崗位!郵箱:bupabuku@foxmail.com.謝謝啦!~
前端加密的意義
這是一個繞不開的話題,肯定有很多看法.但我看來:前端加密看起來有意義,但有時候看起來並沒有"意義". 但總體來看是有意義的,打個比喻:既然市面上大部分鎖都可以在20分鐘內撬開,那門上裝鎖是否還有意義?
有意義:
在 HTTP 協議下,資料是明文傳輸,傳輸過程中網路嗅探可直接獲取其中的資料。 如使用者的密碼和信用卡相關的資料,一旦被中間人獲取,會給使用者帶來極大的安全隱患。另一方面在非加密的傳輸過程中,攻擊者可更改資料或插入惡意的程式碼等。那麼前端加密的意義: 即在資料傳送前將資料進行雜湊或使用公鑰加密。如果資料被中間人獲取,拿到的則不再是明文。
當然還有其他一些優點:例如避免後端等列印日誌直接暴露明文密碼,還可以避免明文撞庫等.
沒有"意義": 前端加密,其實只能防君子不能防小人。 前端系統的控制權是完全在使用者手裡的,也就是說,前端做什麼事情,使用者有完全的控制權。即使前端加密不可以防範中間人攻擊,包括HTTPS,因為中間還是存在著各種代理,客戶端代理,服務端代理.是很難做到不被劫持的.
這裡簡單說下:
- 加密了也無法解決重放的問題,你發給伺服器端的雖然是加密後的資料,但是黑客攔截之後,把加密之後的資料重發一遍,依然是驗證通過的。直接監聽到你所謂的密文,然後用指令碼發起一個http請求就可以登入上去了。 http在網路上是明文傳輸的,代理和閘道器都能夠看到所有的資料,在同一區域網內也可以被嗅探到。加密也沒有提高什麼攻擊難度,因為攻擊者就沒必要去解密原始密碼,能登入上去就表示目標已經實現了,所以,難度沒有提高。
- 既然是加密,那麼加密用的金鑰和演算法肯定是儲存在前端的,攻擊者通過檢視原始碼就能得到演算法和金鑰。除非你是通過做瀏覽器外掛,將演算法和金鑰封裝在外掛中,然後加密的時候明文混淆上時間戳,這樣即使黑客攔截到了請求資料,進行重放過程時,也會很快失效。
總結一下:
- 1,安全是前後端都需要做的事,不能前端加密了,後端就不管了.
- 2,HTTPS還是有必要的,只要正確使用了HTTPS連線和伺服器端安全的雜湊演算法,密碼系統都可以是很安全的。
這裡我只是簡單梳理下,如果還有疑惑想深入探(si)討(bi)的,可以看下逼乎上的這篇文章
前端加密的幾種做法
• JavaScript 加密後傳輸(具體可以參考後面的常見加密方法)
• 瀏覽器外掛內進行加密傳輸 (這個用得不是很多,這裡暫不細究)
• Https 傳輸
加密演算法
不同於雜湊(後面會提到),加密(Encrypt)是將目標文字轉換成具有不同長度的、可逆的密文。也就是說加密演算法是可逆的,而且其加密後生成的密文長度和明文字身的長度有關。所以如果被保護資料在以後需要被還原成明文,則需要使用加密。
在加密演算法中又分為對稱加密(symmetric encryption)和非對稱加密(asymmetric encryption)。
對稱加密
對稱加密採用了對稱密碼編碼技術,它的特點是檔案加密和解密使用相同的金鑰加密.也就是加密和解密都是用同一個金鑰,這種方法在密碼學中叫做對稱加密演算法.
對稱加密演算法使用起來簡單快捷,金鑰較短,且破譯困難,除了資料加密標準(DES),另一個對稱金鑰加密系統是國際資料加密演算法(IDEA),它比DES的加密性好,而且對計算機功能要求也沒有那麼高.
常見的對稱加密演算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES
注意: 因為前端的透明性,對於登入密碼等敏感資訊,就不要使用JavaScript來進行對稱加密. 因為別人可以從前端得到密匙後,可以直接對資訊進行解密!
非對稱加密
非對稱加密演算法需要兩個金鑰:公鑰(publickey)和私鑰(privatekey)。 公鑰與私鑰是一對,如果用公鑰對資料進行加密,只有用對應的私鑰才能解密;如果用私鑰對資料進行加密,那麼只有用對應的公鑰才能解密。 因為加密和解密使用的是兩個不同的金鑰,所以這種演算法叫作非對稱加密演算法。
非對稱加密演算法實現機密資訊交換的基本過程是:甲方生成一對金鑰並將其中的一把作為公鑰向其它方公開;得到該公鑰的乙方使用該金鑰對機密資訊進行加密後再傳送給甲方;甲方再用自己儲存的另一把專用金鑰對加密後的資訊進行解密。甲方只能用其專用金鑰解密由其公鑰加密後的任何資訊。
常見的非對稱加密演算法有:RSA、ECC(移動裝置用)、Diffie-Hellman、El Gamal、DSA(數字簽名用)
雜湊加密演算法
雜湊演算法(Hash)
雜湊(Hash)是將目標文字轉換成具有固定長度的字串(或叫做訊息摘要)。 當輸入發生改變時,產生的雜湊值也是完全不同的。從數學角度上講,一個雜湊演算法是一個多對一的對映關係,對於目標文字 T,演算法 H 可以將其唯一對映為 R,並且對於所有的 T,R 具有相同的長度,所以 H 不存在逆對映,也就是說雜湊演算法是不可逆的。
基於雜湊演算法的特性,其適用於該場景:被保護資料僅僅用作比較驗證且不需要還原成明文形式。比較常用的雜湊演算法是 MD5 和 SHA1 。
我們比較熟悉的使用雜湊儲存資料的例子是:當我們登入某個已註冊網站時,在忘記密碼的情況下需要重置密碼,此時網站會給你發一個隨機的密碼或者一個郵箱啟用連結,而不是將之前的密碼發給你,這就是因為雜湊演算法是不可逆的。
需要注意的是:在 Web 應用中,在瀏覽器中使用雜湊加密的同時也要在服務端上進行雜湊加密。
服務端雜湊加密原因: 一方面因為不需要將密文解密成明文來比對密碼,另一方面是一旦加密演算法和金鑰洩露,那麼整個使用者資料庫就相當於明文儲存了。如果前端傳過來的是明文,那麼在註冊時將其雜湊,存入資料庫。登入時,將密碼雜湊和資料庫對應的資料比對,若一致則說明密碼正確。
現在,對於簡單的雜湊演算法的攻擊方法主要有:尋找碰撞法和窮舉法。所以,為了保證資料的安全,可以在雜湊演算法的基礎上進一步的加密,常見的方法有:加鹽、慢雜湊、金鑰雜湊、XOR 等。
加鹽(Adding Salt)
加鹽加密是一種對系統登入口令的加密方式,它實現的方式是將每一個口令同一個叫做“鹽”(salt)的 n 位隨機數相關聯。
為了方便理解:這裡引用這位同學的文章進行說明:
使用salt加密,它的基本想法是這樣的:
- 1.使用者註冊時,在密碼上撒一些鹽。生成一種味道,記住味道。
- 2.使用者再次登陸時,在輸入的密碼上撒鹽,聞一聞,判斷是否和原來的味道相同,相同就讓你吃飯。
由於驗證密碼時和最初雜湊密碼時使用相同的鹽值,所以salt的儲存在資料庫。並且這個值是由系統隨機產生的,而非硬編碼。這就保證了所要保護物件的機密性。
註冊時:
- 1.使用者註冊,系統隨機產生salt值。
- 2.將salt值和密碼連線起來,生產Hash值。
- 3.將Hash值和salt值分別儲存在資料庫中。
登陸時:
- 1.系統根據使用者名稱找到與之對應的密碼Hash。
- 2.將使用者輸入密碼和salt值進行雜湊。
- 3.判斷生成的Hash值是否和資料庫中Hash相同。
PS: 其實圖中的這種登入也是不安全的. 原因是後面要提到的鹽值複用
使用加鹽加密時需要注意以下兩點:
- 短鹽值(Short Slat)
如果鹽值太短,攻擊者可以預先製作針對所有可能的鹽值的查詢表。例如,如果鹽值只有三個 ASCII 字元,那麼只有 95x95x95=857,375 種可能性,加大了被攻擊的可能性。還有,不要使用可預測的鹽值,比如使用者名稱,因為針對某系統使用者名稱是唯一的且被經常用於其他服務。
- 鹽值複用(Salt Reuse)
在專案開發中,有時會遇到將鹽值寫死在程式裡或者只有第一次是隨機生成的,之後都會被重複使用,這種加鹽方法是不起作用的。以登入密碼為例,如果兩個使用者有相同的密碼,那麼他們就會有相同的雜湊值,攻擊者就可以使用反向查表法對每個雜湊值進行字典攻擊,使得該雜湊值更容易被破解。
所以正確的加鹽方法如下:
(1)鹽值應該使用加密的安全偽隨機數生成器( Cryptographically Secure Pseudo-Random Number Generator,CSPRNG )產生,比如 C 語言的 rand() 函式,這樣生成的隨機數高度隨機、完全不可預測;
(2)鹽值混入目標文字中,一起使用標準的加密函式進行加密;
(3)鹽值要足夠長(經驗表明:鹽值至少要跟雜湊函式的輸出一樣長)且永不重複;
(4)鹽值最好由服務端提供,前端取值使用。
慢雜湊函式(Slow Hash Function)
顧名思義,慢雜湊函式是將雜湊函式變得非常慢,使得攻擊方法也變得很慢,慢到足以令攻擊者放棄,而往往由此帶來的延遲也不會引起使用者的注意。降低攻擊效率用到了金鑰擴充套件( key stretching)的技術,而金鑰擴充套件的實現使用了一種 CPU 密集型雜湊函式( CPU-intensive hash function)。看起來有點暈~還是關注下該函式怎麼用吧!
如果想在一個 Web 應用中使用金鑰擴充套件,則需要設定較低的迭代次數來降低額外的計算成本。我們一般直接選擇使用標準的演算法來完成,比如 PBKDF2 或 bcrypt 。PHP、史丹佛大學的 JavaScript 加密庫都包含了 PBKDF2 的實現,瀏覽器中則可以考慮使用 JavaScript 完成,否則這部分工作應該由服務端進行計算。
金鑰雜湊
金鑰雜湊是將金鑰新增到雜湊加密,這樣只有知道金鑰的人才可以進行驗證。目前有兩種實現方式:使用 ASE 演算法對雜湊值加密、使用金鑰雜湊演算法 HMAC 將金鑰包含到雜湊字串中。為了保證金鑰的安全,需要將其儲存在外部系統(比如一個物理上隔離的服務端)。
即使選擇了金鑰雜湊,在其基礎上進行加鹽或者金鑰擴充套件處理也是很有必要。目前金鑰雜湊用於服務端比較多,例如來應對常見的 SQL 注入攻擊。
XOR
XOR 大家都不陌生,它指的是邏輯運算中的 “異或運算”。兩個值相同時,返回 false,否則返回 true,用來判斷兩個值是否不同。
JavaScript 語言的二進位制運算,有一個專門的 XOR 運算子,寫作^。
1 ^ 1 // 0
0 ^ 0 // 0
1 ^ 0 // 1
0 ^ 1 // 1
複製程式碼
XOR 運算有一個特性:如果對一個值連續做兩次 XOR,會返回這個值本身。這也是其可以用於資訊加密的根本。
message XOR key // cipherText
cipherText XOR key // message
複製程式碼
目標文字 message,key 是金鑰,第一次執行 XOR 會得到加密文字;在加密文字上再用 key 做一次 XOR 就會還原目標文字 message。為了保證 XOR 的安全,需要滿足以下兩點:
(1)key 的長度大於等於 message ;
(2)key 必須是一次性的,且每次都要隨機產生。
下面以登入密碼加密為例介紹下 XOR 的使用:
第一步:使用 MD5 演算法,計算密碼的雜湊;
const message = md5(password);
複製程式碼
第二步:生成一個隨機 key 值;
第三步:進行 XOR 運算,求出加密後的 message。
function getXOR(message, key)
const arr = [];
//假設 key 是32位的
for (let i = 0; i < 32; i++) {
const m = parseInt(message.substr(i, 1), 16);
const k = parseInt(key.substr(i, 1), 16);
arr.push((m ^ k).toString(16));
}
return arr.join('');
}
複製程式碼
如上所示,使用 XOR 和一次性的金鑰 key 對密碼進行加密處理,只要 key 沒有洩露,目標文字就不會被破解。
上面說了那麼多,問題就來了:我們應該使用什麼樣的雜湊演算法呢?
(1)選擇經過驗證的成熟演算法,如 PBKDF2 等 ;
(2)crypt 的安全版本;
(3)避免使用自己設計的加密演算法。
HMAC
對於HMAC演算法,我也不是太瞭解.看了幾篇文章,感覺和加鹽很像,就是salt換成後端隨機生成的(好像可以防止重放攻擊).然後再通過HMAC演算法,得到摘要.
關於HMAC演算法部分可以詳細看這篇文章,我是學渣,看了半天也不是太懂.=.=
大概過程如下:
- 1.客戶端發出登入請求
- 2.伺服器返回一個隨機值,在會話記錄中儲存這個隨機值
- 3.客戶端將該隨機值作為金鑰,使用者密碼進行 hmac 運算,遞交給伺服器
- 4.伺服器讀取資料庫中的使用者密碼,利用金鑰做和客戶端一樣的 hmac運算,然後與使用者傳送的結果比較,如果一致,則使用者身份合法。
好處:
- 與自定義的加salt演算法不同,Hmac演算法針對所有雜湊演算法都通用,無論是MD5還是SHA-1。採用Hmac替代我們自己的salt演算法,可以使程式演算法更標準化,也更安全。(摘自雪峰大佬的這篇文章)
- 另外一個就是密碼的安全性,由於不知道金鑰,所以不可能獲取到使用者密碼
補充1: 結合驗證碼進行前端加密 (其實就是一種動態加鹽雜湊)
前端先將密碼雜湊,然後和使用者輸入的驗證碼進行雜湊,得到的結果作為密碼欄位傳送給伺服器。伺服器先確認驗證碼正確,然後再進行密碼驗證,否則直接返回驗證碼錯誤資訊。
這種實踐保證了密碼在傳輸過程中的資料安全,即使攻擊者拿到了資料也無法重放。圖形化驗證碼更是增加了難度。另一方面該實踐大大增加了撞庫的成本。
前端加密一定程度保障了傳輸過程中的資料安全,那麼會不會有對兩端(客戶端和伺服器)有安全幫助呢?
有幫助,使用一些前端加密手段,可以增加拖庫後的資料破解難度。但是驗證碼方法不具有這樣的功能,因為資料庫存的仍是明文密碼雜湊後的結果,那麼攻擊者可以繞過前端加密,可以直接暴力破解。
補充2: Base64 編碼
大家經常說的是 Base64 加密,有 Base64 加密嗎?真木有,只有 Base64 編碼。
Base64 是一種基於 64 個可列印字元來表示二進位制資料的表示方法。常用於在通常處理文字資料的場合,表示、傳輸、儲存一些二進位制資料,包括 MIME 的 email,email via MIME,在 XML 中儲存複雜資料;主要用來解決把不可列印的內容塞進可列印內容的需求。js中 base64 方法使用如下:
//1.編碼
var result = Base.encode('shotCat好帥!'); //--> "c2hvdENhdOWlveW4hSE="
//2.解碼
var result2 = Base.decode(result); //--> 'shotCat好帥!' 沒錯,我就是這麼不要臉!!!
複製程式碼
因此,Base64 適用於小段內容的編碼,比如數字證照籤名、Cookie的內容等;而且 Base64 也是一種通過查表的編碼方法,不能用於加密,如果需要加密,請使用專業的加密演算法。
PS: 對於前端來說,base64用得最多的也就是圖片轉碼吧.
補充3: 數字簽名
數字簽名主要用於:確認資訊來源於特定的主體且資訊完整、未被篡改,傳送方生成簽名,接收方驗證簽名。
傳送方: 首先計算目標文字的摘要(雜湊值),通過私鑰對摘要進行簽名,將目標文字和電子簽名傳送給接收方。
接收方: 驗證簽名的步驟如下:
- 1,通過公鑰破解電子簽名,得到摘要 D1 (如果失敗,則資訊來源主體校驗失敗);
- 2,計算目標文字摘要 D2;
- 3,若 D1 === D2,則說明目標文字完整、未被篡改。
數字簽名與非對稱加密區別:
- 非對稱加密(加密/解密):公鑰加密,私鑰解密。
- 數字簽名(簽名/驗證):私鑰簽名,公鑰驗證。
HTTPS加密
為了避免重複,這部分內容在本系列-HTTP與HTTPS有詳細介紹