"加鹽"到底加的是什麼

"加鹽"到底加的是什麼

4 人贊了文章今天非常尷尬,因為沒有學過密碼學,而且基於以前用nodejs寫後台和與後台對接的經驗上,單純的認為後台或者資料庫管理員是可以拿到我們的用戶名和密碼的,那麼我們的賬戶其實是出於一個很不安全的狀態。

就算是對密碼做了加密也會用反解密的方式獲得密碼啊。

正好,今天我的wiki密碼忘記了,想叫運維給我改個密碼,然後就聊到了這個話題,(改密碼是操作,是另一個問題,這是可以操作的)。

我拿到資料庫中的賬號密碼就能直接通過某種方式獲得明文密碼了嗎?

在使用nodejs的時候,我經常會用MD5來對數據進行加鹽。

今天的話題就從加鹽開始了,什麼是加鹽呢?

下面引用了一篇文章來講解加鹽,也算一次科普。

鹽(Salt)

在密碼學中,是指通過在密碼任意固定位置插入特定的字元串,讓散列後的結果和使用原始密碼的散列結果不相符,這種過程稱之為「加鹽」。

第一代密碼

早期的軟體系統或者互聯網應用,資料庫中設計用戶表的時候,大致是這樣的結構:

mysql> desc User;+----------+--------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+----------+--------------+------+-----+---------+-------+| UserName | varchar(50) | NO | | | || PassWord | varchar(150) | NO | | | |+----------+--------------+------+-----+---------+-------+

數據存儲形式如下:

mysql> select * from User;+----------+----------+| UserName | PassWord |+----------+----------+| lichao | 123 || akasuna | 456 |+----------+----------+

主要的關鍵欄位就是這麼兩個,一個是登陸時的用戶名,對應的一個密碼,而且那個時候的用戶名是明文存儲的,如果你登陸時用戶名是 123,那麼資料庫里存的就是 123。這種設計思路非常簡單,但是缺陷也非常明顯,資料庫一旦泄露,那麼所有用戶名和密碼都會泄露,後果非常嚴重。參見《CSDN 詳解 600 萬用戶密碼泄露始末》。

第二代密碼

為了規避第一代密碼設計的缺陷,聰明的人在資料庫中不在存儲明文密碼,轉而存儲加密後的密碼,典型的加密演算法是 MD5 和 SHA1,其數據表大致是這樣設計的:

mysql> desc User;+----------+--------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+----------+--------------+------+-----+---------+-------+| UserName | varchar(50) | NO | | | || PwdHash | char(32) | NO | | | |+----------+--------------+------+-----+---------+-------+

數據存儲形式如下:

mysql> select * from User;+----------+----------------------------------+| UserName | PwdHash |+----------+----------------------------------+| lichao | 202cb962ac59075b964b07152d234b70 || akasuna | 250cf8b51c773f3f8dc8b4be867a9a02 |+----------+----------------------------------+

假如你設置的密碼是 123,那麼資料庫中存儲的就是 202cb962ac59075b964b07152d234b70 或 40bd001563085fc35165329ea1ff5c5ecbdbbeef。當用戶登陸的時候,會把用戶輸入的密碼執行 MD5(或者 SHA1)後再和資料庫就行對比,判斷用戶身份是否合法,這種加密演算法稱為散列。

嚴格地說,這種演算法不能算是加密,因為理論上來說,它不能被解密。所以即使資料庫丟失了,但是由於資料庫里的密碼都是密文,根本無法判斷用戶的原始密碼,所以後果也不算太嚴重。

第三代密碼

本來第二代密碼設計方法已經很不錯了,只要你密碼設置得稍微複雜一點,就幾乎沒有被破解的可能性。但是如果你的密碼設置得不夠複雜,被破解出來的可能性還是比較大的。

好事者收集常用的密碼,然後對他們執行 MD5 或者 SHA1,然後做成一個數據量非常龐大的數據字典,然後對泄露的資料庫中的密碼就行對比,如果你的原始密碼很不幸的被包含在這個數據字典中,那麼花不了多長時間就能把你的原始密碼匹配出來。這個數據字典很容易收集,CSDN 泄露的那 600w 個密碼,就是很好的原始素材。

於是,第三代密碼設計方法誕生,用戶表中多了一個欄位:

mysql> desc User;+----------+-------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+----------+-------------+------+-----+---------+-------+| UserName | varchar(50) | NO | | | || Salt | char(50) | NO | | | || PwdHash | char(32) | NO | | | |+----------+-------------+------+-----+---------+-------+

數據存儲形式如下:

mysql> select * from User;+----------+----------------------------+----------------------------------+| UserName | Salt | PwdHash |+----------+----------------------------+----------------------------------+| lichao | 1ck12b13k1jmjxrg1h0129h2lj | 6c22ef52be70e11b6f3bcf0f672c96ce || akasuna | 1h029kh2lj11jmjxrg13k1c12b | 7128f587d88d6686974d6ef57c193628 |+----------+----------------------------+----------------------------------+

Salt 可以是任意字母、數字、或是字母或數字的組合,但必須是隨機產生的,每個用戶的 Salt 都不一樣,用戶註冊的時候,資料庫中存入的不是明文密碼,也不是簡單的對明文密碼進行散列,而是 MD5( 明文密碼 + Salt),也就是說:

MD5(123 + 1ck12b13k1jmjxrg1h0129h2lj) = 6c22ef52be70e11b6f3bcf0f672c96ceMD5(456 + 1h029kh2lj11jmjxrg13k1c12b) = 7128f587d88d6686974d6ef57c193628

當用戶登陸的時候,同樣用這種演算法就行驗證。

由於加了 Salt,即便資料庫泄露了,但是由於密碼都是加了 Salt 之後的散列,壞人們的數據字典已經無法直接匹配,明文密碼被破解出來的概率也大大降低。

是不是加了 Salt 之後就絕對安全了呢?淡然沒有!壞人們還是可以他們數據字典中的密碼,加上我們泄露資料庫中的 Salt,然後散列,然後再匹配。但是由於我們的 Salt 是隨機產生的,假如我們的用戶數據表中有 30w 條數據,數據字典中有 600w 條數據,壞人們如果想要完全覆蓋的壞,他們加上 Salt 後再散列的數據字典數據量就應該是 300000* 6000000 = 1800000000000,一萬八千億啊,幹壞事的成本太高了吧。但是如果只是想破解某個用戶的密碼的話,只需為這 600w 條數據加上 Salt,然後散列匹配。可見 Salt 雖然大大提高了安全係數,但也並非絕對安全。

實際項目中,Salt 不一定要加在最前面或最後面,也可以插在中間嘛,也可以分開插入,也可以倒序,程序設計時可以靈活調整,都可以使破解的難度指數級增長。

什麼是加鹽


推薦閱讀:

單身的快快看過來,計算機高手強勢助你脫單!!!
2000 個量子比特模擬成功!量子計算機已可用於解決問題
計算機數學小書1-原碼,反碼和補碼
兩張圖帶你入門數值科學
U盤載入速度慢如何去解決?

TAG:前端開發 | 計算機技術 |