加密算法中鹽的作用

原文鏈接:https://www.cnblogs.com/birdsmaller/p/5377104.html

由來

         涉及身份驗證的系統都需要存儲用戶的認證信息,常用的用戶認證方式主要爲用戶名和密碼的方式,爲了安全起見,用戶輸入的密碼需要保存爲密文形式,可採用已公開的不可逆的hash加密算法,比如SHA256, SHA512, SHA3等,對於同一密碼,同一加密算法會產生相同的hash值,這樣,當用戶進行身份驗證時,也可對用戶輸入的明文密碼應用相同的hash加密算法,得出一個hash值,然後使用該hash值和之前存儲好的密文值進行對照,如果兩個值相同,則密碼認證成功,否則密碼認證失敗。

        由於密碼是由用戶設定的,在實際應用中,用戶設置的密碼複雜度可能不夠高,同時不同的用戶極有可能會使用相同的密碼,那麼這些用戶對應的密文也會相同,這樣,當存儲用戶密碼的數據庫泄露後,攻擊者會很容易便能找到相同密碼的用戶,從而也降低了破解密碼的難度,因此,在對用戶密碼進行加密時,需要考慮對密碼進行掩飾,即使是相同的密碼,也應該要保存爲不同的密文,即使用戶輸入的是弱密碼,也需要考慮進行增強,從而增加密碼被攻破的難度,而使用帶鹽的加密hash值便能滿足該需求

      其實這裏所說的鹽,簡單的說,就是一組安全隨機數。它會在特定的時候,加入到密碼中(一般來說是加密後的密碼

常用的密碼攻擊方式有字典攻擊、暴力破解、查表法、反向查表法、彩虹表等。

常用的密碼攻擊方式

字典攻擊暴力破解,攻擊者均採用逐密碼嘗試的方式,目前沒有很好的手段來阻止字典攻擊和暴力破解攻擊,只能是想辦法讓這兩種攻擊方式變得相對低效一些而相同的密碼產生不同的hash值便能讓攻擊者針對每一個hash值都需要從頭進行嘗試,從而使攻擊變得更加低效。

查表法反向查表法彩虹表攻擊方式,攻擊者需要提前準備好包含密碼和密碼hash值的密碼錶,然後根據該表和用戶密碼數據庫進行批量匹配,從而達到攻破密碼的目的;而如果我們在加密時,給每個密碼附加了不同的隨機值,這樣每個密碼對應的hash值也會不同,這樣攻擊者在準備密碼錶時,就必須要將最基本的密碼和用戶密碼數據庫中的值進行笛卡爾積後再計算hash值,鹽值越多,用戶需要準備的表量越大,這樣對於攻擊而言,就變得有些得不償失了。

加鹽的注意事項

1、鹽值不能太短;如果鹽值只有少數兩三位甚至一兩位的話,攻擊者完全可以窮舉所有可能的鹽值;關於鹽值長度的一個經驗值是長度至少要和hash加密函數的返回值長度保持一致。

2、鹽值不能固定;如果系統使用了固定的鹽值,那麼和不加鹽相當於是一回事了,攻擊者完全可以使用該固定的鹽值提前準備密碼錶;另外,相同密碼對應的hash值仍然是一樣的,仍然無法對密碼相同這一事實進行掩飾。

3、不要使用能提前預知的值作爲鹽值;如果鹽值能提前得知或提前推斷出,攻擊者也完全可以根據提前預知的鹽值準備密碼錶,從而對破解的難度也增加不了多少。

4、每一次修改密碼重新計算hash值時,要重新生成新的鹽值,不要使用上次密碼對應的鹽值;因爲如果用戶密碼泄露之後,鹽值相應的也就泄露了,用戶修改密碼時,如果還沿用原來的鹽值,攻擊者也仍然可以根據上次的鹽值提前準備密碼錶,從而使攻破可能性變得更高了。

數據庫泄露

      衆所周知,用戶名和密碼是被保存在數據庫中。可是一旦數據庫發生了泄露,用戶名和密碼就都遭到了泄露。攻擊者可以輕鬆的獲取用戶名和密碼,進行操作。更大的危害是,由於現在需要註冊的網站、app越來越多。用戶名和密碼很多時候都是相同的。一旦某處發生了泄露,則後果會慢慢的擴散。這些危害大家可以查詢下近些年發生的一些安全事故,如Sony數據庫泄露、網易數據庫泄露、CSDN數據庫泄露等。

解決這個問題的通用方法是:

1、對密碼進行加密存儲

      這樣的好處是,即使數據庫發生了泄露,攻擊者也不會拿到明文密碼,依然無法直接使用這些密碼。但是這樣的存儲方式也存在缺點:很多用戶在註冊時都是使用的弱密碼。攻擊者可以通過大量的註冊用戶,這些用戶使用擴散的使用各種弱密碼。當拿到數據庫密文後,根據已知的用戶名密碼,就可以獲取到相關的彩虹表。然後依據彩虹表依次匹配數據庫中的密碼。這樣就可以得到其中使用弱密碼的用戶了。同時app、web等軟件由於用戶體驗等原因,也不可能讓用戶設置安全係數過高的密碼。如8位以上、包含大小寫、特殊字符、於最近三次的密碼不能相同、於上次密碼至少有三位不同、不能包含密碼字典中涉及的簡單密碼等等。舉個例子:如ATM、微信支付密碼使用的是純6位數字,這樣就有了10^6種可能,攻擊者只要拿到了全套的密碼對應的彩虹表,就可以獲取到所有用戶的密碼。這套彩虹表,攻擊者可以通過使用大量的簡單密碼註冊用戶得到。然後從獲取到的數據庫中找到攻擊者自己註冊的這些用戶數據,進而拿到彩虹表。那麼該怎麼解決呢?這就涉及到固定鹽值加密。

2、對密碼進行加密

如前文所說,這個鹽是一個隨機數。當用戶註冊一個簡單密碼時,系統會同時生成這樣一個salt,於該用戶對應,保存到數據庫中。

這樣當用戶的密碼是888888時,後臺真實存儲的密碼時888888鹽化以後的值

操作步驟如下:

(1)註冊、修改密碼時,前臺將 888888加密後的pwd1,傳入後臺

(2)後臺拿到pwd1以後,生成一個相應的隨機數 salt。將pwd1與salt拼接並再次加密,生成pwd2

(3)後臺將pwd2salt 一併存儲到數據庫中。

(4)當用戶每次輸入用戶名密碼後,將密碼加密生成pwd1'後,傳入後臺。

(5)後臺拿到pwd1'後,根據用戶名id拿到對應的鹽值。與鹽值拼接加密後,生成pwd2‘。

(6)然後判斷pwd2'與數據庫中的pwd2是否一致即可。

這裏有兩點需要注意:

①密碼在前後臺的加密方式可以採用不同的形式

②鹽值的拼接不一定非要拼接到最後,也可以放在前邊、插在中間、甚至拆開或者倒序拼接。

③這樣即使是簡單密碼也沒關係。因爲相同的密碼在數據庫中存儲的值並不一樣。攻擊者無法構造有效的彩虹表進行破解。

重放攻擊

  先拋開前邊的固化鹽值加密不說,我們再說說另外一種攻擊方式:重放攻擊(Replay Attacks)又叫重播攻擊、回放攻擊或新鮮性攻擊(Freshness Attacks)。

  這裏舉個簡單的例子:當用戶A進行登錄後,前臺會將加密後的密碼,以數據包的形式發送到服務端。服務端會進行鹽化等加密手段後,再進行安全校驗。可是如果這個數據包被攻擊者截獲。並且分析出數據包的結構(如哪些字段代表用戶名、哪些代表IP/會話ID),然後進行適當的修改,再次發送給服務端後,服務端依然會進行常規的校驗,依然會驗證通過。也就是說無論客戶端,服務端的加密手段多麼的複雜,一旦攻擊者有能力截獲和修改前後臺通信的數據包,那麼這些加密手段都將不起作用。

那麼如何防範呢?仔細想想重放攻擊,攻擊者利用的是每次發送的包中用戶名密碼等部分不變的機理。

那麼我們可以讓他改變,怎麼改變呢?

大致思路如下:

1、每次登陸時,我們可以生成一個隨機數(一個動態生成的salt),這個salt在前後臺各自保存一份。

2、當用戶名輸入完密碼pwd後。前臺會進行 f1(pwd)加密,然後與動態生成的salt拼接,然後再次加密。

也就是 pwd1=f2(f1(pwd)+salt)。之後前臺就把這個pwd1發送到後臺。(注意由於動態salt每次都會改變,所以pwd1每次也會改變)

3、後臺拿到數據後,如果沒有使用固化鹽值加密的話,直接將數據庫中的數據採用相同的方式與服務端保存的動態salt拼接加密然後再對比即可。

如果同時存在固化鹽值加密的話,需要想辦法剔除掉這個動態salt(即f2()使用可逆的機密算法),然後再拼接固化salt接着再次加密,最後與數據庫對比即可

參考:https://www.cnblogs.com/birdsmaller/p/5377104.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章