本系列最開始是爲了本身面試準備的.後來發現整理愈來愈多,差很少有十二萬字符,最後決定仍是分享出來給你們.前端
爲了分享整理出來,花費了本身大量的時間,起碼是隻本身用的三倍時間.若是喜歡的話,歡迎收藏,關注我!謝謝!vue
前端面試查漏補缺--Index篇(12萬字符合集) 包含目前已寫好的系列其餘十幾篇文章.後續新增值文章不會再在每篇添加連接,強烈建議議點贊,關注合集篇!!!!,謝謝!~面試
後續還會繼續添加設計模式,前端工程化,項目流程,部署,閉環,vue常考知識點 等內容.若是以爲內容不錯的話歡迎收藏,關注我!謝謝!算法
目前本人也在準備跳槽,但願各位大佬和HR小姐姐能夠內推一份靠譜的武漢 前端崗位!郵箱:bupabuku@foxmail.com.謝謝啦!~數據庫
這是一個繞不開的話題,確定有不少見解.但我看來:前端加密看起來有意義,但有時候看起來並無"意義". 但整體來看是有意義的,打個比喻:既然市面上大部分鎖均可以在20分鐘內撬開,那門上裝鎖是否還有意義?後端
有意義:
在 HTTP 協議下,數據是明文傳輸,傳輸過程當中網絡嗅探可直接獲取其中的數據。 如用戶的密碼和信用卡相關的資料,一旦被中間人獲取,會給用戶帶來極大的安全隱患。另外一方面在非加密的傳輸過程當中,攻擊者可更改數據或插入惡意的代碼等。那麼前端加密的意義: 即在數據發送前將數據進行哈希或使用公鑰加密。若是數據被中間人獲取,拿到的則再也不是明文。設計模式
固然還有其餘一些優勢:例如避免後端等打印日誌直接暴露明文密碼,還能夠避免明文撞庫等.前端工程化
沒有"意義": 前端加密,其實只能防君子不能防小人。 前端系統的控制權是徹底在用戶手裏的,也就是說,前端作什麼事情,用戶有徹底的控制權。即便前端加密不能夠防範中間人攻擊,包括HTTPS,由於中間仍是存在着各類代理,客戶端代理,服務端代理.是很難作到不被劫持的.跨域
這裏簡單說下:瀏覽器
總結一下:
這裏我只是簡單梳理下,若是還有疑惑想深刻探(si)討(bi)的,能夠看下逼乎上的這篇文章
• JavaScript 加密後傳輸(具體能夠參考後面的常見加密方法)
• 瀏覽器插件內進行加密傳輸 (這個用得不是不少,這裏暫不細究)
• Https 傳輸
不一樣於哈希(後面會提到),加密(Encrypt)是將目標文本轉換成具備不一樣長度的、可逆的密文。也就是說加密算法是可逆的,並且其加密後生成的密文長度和明文自己的長度有關。因此若是被保護數據在之後須要被還原成明文,則須要使用加密。
在加密算法中又分爲對稱加密(symmetric encryption)和非對稱加密(asymmetric encryption)。
對稱加密採用了對稱密碼編碼技術,它的特色是文件加密和解密使用相同的密鑰加密.也就是加密和解密都是用同一個密鑰,這種方法在密碼學中叫作對稱加密算法.
對稱加密算法使用起來簡單快捷,密鑰較短,且破譯困難,除了數據加密標準(DES),另外一個對稱密鑰加密系統是國際數據加密算法(IDEA),它比DES的加密性好,並且對計算機功能要求也沒有那麼高.
常見的對稱加密算法有DES、3DES、Blowfish、IDEA、RC四、RC五、RC6和AES
注意: 由於前端的透明性,對於登陸密碼等敏感信息,就不要使用JavaScript來進行對稱加密. 由於別人能夠從前端獲得密匙後,能夠直接對信息進行解密!
非對稱加密算法須要兩個密鑰:公鑰(publickey)和私鑰(privatekey)。 公鑰與私鑰是一對,若是用公鑰對數據進行加密,只有用對應的私鑰才能解密;若是用私鑰對數據進行加密,那麼只有用對應的公鑰才能解密。 由於加密和解密使用的是兩個不一樣的密鑰,因此這種算法叫做非對稱加密算法。
非對稱加密算法實現機密信息交換的基本過程是:甲方生成一對密鑰並將其中的一把做爲公鑰向其它方公開;獲得該公鑰的乙方使用該密鑰對機密信息進行加密後再發送給甲方;甲方再用本身保存的另外一把專用密鑰對加密後的信息進行解密。甲方只能用其專用密鑰解密由其公鑰加密後的任何信息。
常見的非對稱加密算法有:RSA、ECC(移動設備用)、Diffie-Hellman、El Gamal、DSA(數字簽名用)
哈希(Hash)是將目標文本轉換成具備固定長度的字符串(或叫作消息摘要)。 當輸入發生改變時,產生的哈希值也是徹底不一樣的。從數學角度上講,一個哈希算法是一個多對一的映射關係,對於目標文本 T,算法 H 能夠將其惟一映射爲 R,而且對於全部的 T,R 具備相同的長度,因此 H 不存在逆映射,也就是說哈希算法是不可逆的。
基於哈希算法的特性,其適用於該場景:被保護數據僅僅用做比較驗證且不須要還原成明文形式。比較經常使用的哈希算法是 MD5 和 SHA1 。
咱們比較熟悉的使用哈希存儲數據的例子是:當咱們登陸某個已註冊網站時,在忘記密碼的狀況下須要重置密碼,此時網站會給你發一個隨機的密碼或者一個郵箱激活連接,而不是將以前的密碼發給你,這就是由於哈希算法是不可逆的。
須要注意的是:在 Web 應用中,在瀏覽器中使用哈希加密的同時也要在服務端上進行哈希加密。
服務端哈希加密緣由: 一方面由於不須要將密文解密成明文來比對密碼,另外一方面是一旦加密算法和密鑰泄露,那麼整個用戶資料庫就至關於明文存儲了。若是前端傳過來的是明文,那麼在註冊時將其哈希,存入數據庫。登陸時,將密碼哈希和數據庫對應的數據比對,若一致則說明密碼正確。
如今,對於簡單的哈希算法的攻擊方法主要有:尋找碰撞法和窮舉法。因此,爲了保證數據的安全,能夠在哈希算法的基礎上進一步的加密,常見的方法有:加鹽、慢哈希、密鑰哈希、XOR 等。
加鹽加密是一種對系統登陸口令的加密方式,它實現的方式是將每個口令同一個叫作「鹽」(salt)的 n 位隨機數相關聯。
爲了方便理解:這裏引用這位同窗的文章進行說明:
使用salt加密,它的基本想法是這樣的:
因爲驗證密碼時和最初散列密碼時使用相同的鹽值,因此salt的存儲在數據庫。而且這個值是由系統隨機產生的,而非硬編碼。這就保證了所要保護對象的機密性。
註冊時:
登錄時:
PS: 其實圖中的這種登陸也是不安全的. 緣由是後面要提到的鹽值複用
使用加鹽加密時須要注意如下兩點:
若是鹽值過短,攻擊者能夠預先製做針對全部可能的鹽值的查詢表。例如,若是鹽值只有三個 ASCII 字符,那麼只有 95x95x95=857,375 種可能性,加大了被攻擊的可能性。還有,不要使用可預測的鹽值,好比用戶名,由於針對某系統用戶名是惟一的且被常常用於其餘服務。
在項目開發中,有時會遇到將鹽值寫死在程序裏或者只有第一次是隨機生成的,以後都會被重複使用,這種加鹽方法是不起做用的。以登陸密碼爲例,若是兩個用戶有相同的密碼,那麼他們就會有相同的哈希值,攻擊者就可使用反向查表法對每一個哈希值進行字典攻擊,使得該哈希值更容易被破解。
因此正確的加鹽方法以下:
(1)鹽值應該使用加密的安全僞隨機數生成器( Cryptographically Secure Pseudo-Random Number Generator,CSPRNG )產生,好比 C 語言的 rand() 函數,這樣生成的隨機數高度隨機、徹底不可預測;
(2)鹽值混入目標文本中,一塊兒使用標準的加密函數進行加密;
(3)鹽值要足夠長(經驗代表:鹽值至少要跟哈希函數的輸出同樣長)且永不重複;
(4)鹽值最好由服務端提供,前端取值使用。
顧名思義,慢哈希函數是將哈希函數變得很是慢,使得攻擊方法也變得很慢,慢到足以令攻擊者放棄,而每每由此帶來的延遲也不會引發用戶的注意。下降攻擊效率用到了密鑰擴展( key stretching)的技術,而密鑰擴展的實現使用了一種 CPU 密集型哈希函數( CPU-intensive hash function)。看起來有點暈~仍是關注下該函數怎麼用吧!
若是想在一個 Web 應用中使用密鑰擴展,則須要設定較低的迭代次數來下降額外的計算成本。咱們通常直接選擇使用標準的算法來完成,好比 PBKDF2 或 bcrypt 。PHP、斯坦福大學的 JavaScript 加密庫都包含了 PBKDF2 的實現,瀏覽器中則能夠考慮使用 JavaScript 完成,不然這部分工做應該由服務端進行計算。
密鑰哈希是將密鑰添加到哈希加密,這樣只有知道密鑰的人才能夠進行驗證。目前有兩種實現方式:使用 ASE 算法對哈希值加密、使用密鑰哈希算法 HMAC 將密鑰包含到哈希字符串中。爲了保證密鑰的安全,須要將其存儲在外部系統(好比一個物理上隔離的服務端)。
即便選擇了密鑰哈希,在其基礎上進行加鹽或者密鑰擴展處理也是頗有必要。目前密鑰哈希用於服務端比較多,例如來應對常見的 SQL 注入攻擊。
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算法,我也不是太瞭解.看了幾篇文章,感受和加鹽很像,就是salt換成後端隨機生成的(好像能夠防止重放攻擊).而後再經過HMAC算法,獲得摘要.
關於HMAC算法部分能夠詳細看這篇文章,我是學渣,看了半天也不是太懂.=.=
大概過程以下:
好處:
前端先將密碼哈希,而後和用戶輸入的驗證碼進行哈希,獲得的結果做爲密碼字段發送給服務器。服務器先確認驗證碼正確,而後再進行密碼驗證,不然直接返回驗證碼錯誤信息。
這種實踐保證了密碼在傳輸過程當中的資料安全,即便攻擊者拿到了數據也沒法重放。圖形化驗證碼更是增長了難度。另外一方面該實踐大大增長了撞庫的成本。
前端加密必定程度保障了傳輸過程當中的資料安全,那麼會不會有對兩端(客戶端和服務器)有安全幫助呢?
有幫助,使用一些前端加密手段,能夠增長拖庫後的數據破解難度。可是驗證碼方法不具備這樣的功能,由於數據庫存的還是明文密碼哈希後的結果,那麼攻擊者能夠繞過前端加密,能夠直接暴力破解。
你們常常說的是 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用得最多的也就是圖片轉碼吧.
數字簽名主要用於:確認信息來源於特定的主體且信息完整、未被篡改,發送方生成簽名,接收方驗證簽名。
發送方: 首先計算目標文本的摘要(哈希值),經過私鑰對摘要進行簽名,將目標文本和電子簽名發送給接收方。
接收方: 驗證簽名的步驟以下:
數字簽名與非對稱加密區別:
爲了不重複,這部份內容在本系列-HTTP與HTTPS有詳細介紹