一文說(shuō)透密碼安全存儲(chǔ)

趙鑫
如果密碼是加密之后再存儲(chǔ),那么即便被拖庫(kù),黑客也難以獲取用戶的明文密碼??梢哉f(shuō),密碼加密存儲(chǔ)是用戶賬戶系統(tǒng)的底褲,它的重要性,相當(dāng)于你獨(dú)自出遠(yuǎn)門時(shí)縫在內(nèi)衣里錢,雖然你用到他們的概率不大,但關(guān)鍵時(shí)刻他們能救命。

我們數(shù)據(jù)庫(kù)的權(quán)限管理十分嚴(yán)格,敏感信息開(kāi)發(fā)工程師都看不到,密碼明文存儲(chǔ)不行嗎?

不行。存儲(chǔ)在數(shù)據(jù)庫(kù)的數(shù)據(jù)面臨很多威脅,有應(yīng)用程序?qū)用?、?shù)據(jù)庫(kù)層面的、操作系統(tǒng)層面的、機(jī)房層面的、員工層面的,想做到百分百不被黑客竊取,非常困難。

如果密碼是加密之后再存儲(chǔ),那么即便被拖庫(kù),黑客也難以獲取用戶的明文密碼??梢哉f(shuō),密碼加密存儲(chǔ)是用戶賬戶系統(tǒng)的底褲,它的重要性,相當(dāng)于你獨(dú)自出遠(yuǎn)門時(shí)縫在內(nèi)衣里錢,雖然你用到他們的概率不大,但關(guān)鍵時(shí)刻他們能救命。

那用加密算法比如AES,把密碼加密下再存,需要明文的時(shí)候我再解密。

不行。這涉及到怎么保存用來(lái)加密解密的密鑰,雖然密鑰一般跟用戶信息分開(kāi)存儲(chǔ),且業(yè)界也有一些成熟的、基于軟件或硬件的密鑰存儲(chǔ)方案。但跟用戶信息的保存一樣,想要密鑰百分百不泄露,不可能做到。用這種方式加密密碼,能夠降低黑客獲取明文密碼的概率。但密鑰一旦泄露,用戶的明文密碼也就泄露了,不是一個(gè)好方法。

另外,用戶賬戶系統(tǒng)不應(yīng)該保存用戶的明文密碼,在用戶忘記密碼的時(shí)候,提供重置密碼的功能而不是找回密碼。

保存所有密碼的HASH值,比如MD5。是不是就可以了?

不是所有的HASH算法都可以,準(zhǔn)確講應(yīng)該是Cryptographic Hash。Cryptographic Hash具有如下幾個(gè)特點(diǎn):

給定任意大小任意類型的輸入,計(jì)算hash非???;

給定一個(gè)hash,沒(méi)有辦法計(jì)算得出該hash所對(duì)應(yīng)的輸入;

對(duì)輸入做很小改動(dòng),hash就會(huì)發(fā)生很大變化;

沒(méi)有辦法計(jì)算得到兩個(gè)hash相同的輸入;

雖然不是為加密密碼而設(shè)計(jì),但其第2、3、4三個(gè)特性使得Cryptographic Hash非常適合用來(lái)加密用戶密碼。常見(jiàn)的Cryptographic Hash有MD5、SHA-1、SHA-2、SHA-3/Keccak、BLAKE2。

從1976年開(kāi)始,業(yè)界開(kāi)始使用Cryptographic Hash加密用戶密碼,最早見(jiàn)于Unix Crypt。但MD5、SHA-1已被破解,不適合再用來(lái)保存密碼。

那我保存用戶密碼的SHA256值。

不行。黑客可以用查詢表或彩虹表來(lái)破解用戶密碼。注意是破解密碼不是破解sha256,能根據(jù)sha256破解密碼的原因是,用戶密碼往往需要大腦記憶、手工輸入,所以不會(huì)太復(fù)雜,往往具有有限的長(zhǎng)度、確定的取值空間。

短的取值簡(jiǎn)單的密碼可以用查詢表破解

比如8位數(shù)字密碼,一共只有10^8=100000000種可能。一億條數(shù)據(jù)并不算多,黑客可以提前吧0-99999999的sha256都計(jì)算好,并以sha256做key密碼為value存儲(chǔ)為一個(gè)查詢表,當(dāng)給定sha256需要破解時(shí),從表中查詢即可。

取值相對(duì)復(fù)雜,且長(zhǎng)度較長(zhǎng)的密碼,可以用彩虹表破解

比如10位,允許數(shù)字、字母大小寫的密碼,一共有(10+26+26)^10~=84億億種可能,記錄非常之多難以用查詢表全部保存起來(lái)。這時(shí)候黑客會(huì)用一種叫做彩虹表的技術(shù)來(lái)破解,彩虹表用了典型的計(jì)算機(jī)世界里解決問(wèn)題的思路,時(shí)間空間妥協(xié)。

在這個(gè)例子里面,空間不夠,那就多花一些時(shí)間。在彩虹表中,可以將全部的sha256值轉(zhuǎn)化為長(zhǎng)度相同的若干條hash鏈,只保存hash鏈的頭和尾,在破解的時(shí)候先查詢得到sha256存在于哪條hash鏈中,然后計(jì)算這一條hash鏈上的所有sha256,通過(guò)實(shí)時(shí)比對(duì)來(lái)破解用戶密碼。

上圖圖展示了一個(gè)hash鏈長(zhǎng)度為3的彩虹表,因?yàn)樵趆ash鏈中需要將hash值使用R函數(shù)映射回密碼取值空間,為了降低R函數(shù)的沖突概率,長(zhǎng)度為K的hash鏈中,彩虹表會(huì)使用k個(gè)R函數(shù),因?yàn)槊看蔚成浠孛艽a空間使用的R函數(shù)不一樣,這種破解方法被稱作彩虹表攻擊。

實(shí)際的情況Hash鏈要比遠(yuǎn)比上例更長(zhǎng),比如我們的例子中全部的84億億個(gè)sha256存不下,可以轉(zhuǎn)化為840億條長(zhǎng)度為1千萬(wàn)的sha鏈。對(duì)彩虹表原理感興趣的話,可以閱讀它的維基百科。

網(wǎng)路上甚至有一些已經(jīng)計(jì)算好的彩虹表可以直接使用,所以直接保存用戶密碼的sha256是非常不安全的。

怎樣避免彩虹表攻擊?

簡(jiǎn)單講,就是加鹽。一般來(lái)講用戶密碼是個(gè)字符串key、鹽是我們生成的字符串salt。原來(lái)我們保存的是key的hash值HASH(key),現(xiàn)在我們保存key和salt拼接在一起的hash值HASH(key+salt)。

這樣黑客提前計(jì)算生成的彩虹表,就全都失效了。

鹽應(yīng)該怎么生成,隨機(jī)生成一個(gè)字符串?

這是個(gè)好問(wèn)題,并不是加個(gè)鹽就安全了,鹽的生成有很多講究。

使用CSPRNG(Cryptographically Secure Pseudo-Random Number Generator)生成鹽,而不是普通的隨機(jī)數(shù)算法;

CSPRNG跟普通的隨機(jī)數(shù)生成算法,比如C語(yǔ)言標(biāo)準(zhǔn)庫(kù)里面的rand()方法,有很大不同。正如它的名字所揭示,CSPRNG是加密安全的,這意味著用它產(chǎn)生的隨機(jī)數(shù)更加隨機(jī),且不可預(yù)測(cè)。常見(jiàn)編程語(yǔ)言都提供了CSPRNG,如下表:

鹽不能太短

想想查詢表和彩虹表的原理,如果鹽很短,那意味著密碼+鹽組成的字符串的長(zhǎng)度和取值空間都有限。黑客完全可以為密碼+鹽的所有組合建立彩虹表。

鹽不能重復(fù)使用

如果所有用戶的密碼都使用同一個(gè)鹽進(jìn)行加密。那么不管鹽有多復(fù)雜、多大的長(zhǎng)度,黑客都可以很容易的使用這個(gè)固定鹽重新建立彩虹表,破解你的所有用戶的密碼。如果你說(shuō),我可以把固定鹽存起來(lái),不讓別人知道啊,那么你應(yīng)該重新讀一下我關(guān)于為什么使用AES加密不夠安全的回答。

即便你為每一個(gè)用戶生成一個(gè)隨機(jī)鹽,安全性仍然不夠,因?yàn)檫@個(gè)鹽在用戶修改密碼時(shí)重復(fù)使用了。應(yīng)當(dāng)在每一次需要保存新的密碼時(shí),都生成一個(gè)新的鹽,并跟加密后的hash值保存在一起。

注意:有些系統(tǒng)用一個(gè)每個(gè)用戶都不同的字段,uid、手機(jī)號(hào)、或者別的什么,來(lái)作為鹽加密密碼。這不是一個(gè)好主意,這幾乎違背了上面全部三條鹽的生成規(guī)則。

那我自己設(shè)計(jì)一個(gè)黑客不知道的HASH算法,這樣你的那些破解方法就都失效了。

不可以。

首先如果你不是一個(gè)密碼學(xué)專家,你很難設(shè)計(jì)出一個(gè)安全的hash算法。不服氣的話,你可以再看一遍上面我關(guān)于Cryptographic Hash的描述,然后想一想自己怎么設(shè)計(jì)一個(gè)算法可以滿足它的全部四種特性。就算你是基于已有的Cryptographic Hash的基礎(chǔ)上去設(shè)計(jì),設(shè)計(jì)完之后,也難以保證新算法仍然滿足Cryptographic Hash的要求。而一旦你的算法不滿足安全要求,那么你給了黑客更多更容易破解用戶密碼的方法。

即便你能設(shè)計(jì)出一個(gè)別人不知道的Cryptographic Hash算法,你也不能保證黑客永遠(yuǎn)都不知道你的算法。黑客往往都有能力訪問(wèn)你的代碼,想想柯克霍夫原則或者香農(nóng)公里:

密碼系統(tǒng)應(yīng)該就算被所有人知道系統(tǒng)的運(yùn)作步驟,仍然是安全的。

為每一個(gè)密碼都加上不同的高質(zhì)量的鹽,做HASH,然后保存。這樣可以了吧?

以前是可以的,現(xiàn)在不行了。計(jì)算機(jī)硬件飛速發(fā)展,一個(gè)現(xiàn)代通用CPU能以每月數(shù)百萬(wàn)次的速度計(jì)算sha256,而GPU集群計(jì)算sha256,更是可以達(dá)到每秒10億次以上。這使得暴力破解密碼成為可能,黑客不再依賴查詢表或彩虹表,而是使用定制過(guò)的硬件和專用算法,直接計(jì)算每一種可能,實(shí)時(shí)破解用戶密碼。

那怎么辦呢?回想上面關(guān)于Cryptographic Hash特性的描述,其中第一條:

給定任意大小任意類型的輸入,計(jì)算hash非???/strong>

Cryptographic Hash并不是為了加密密碼而設(shè)計(jì)的,它計(jì)算非??斓倪@個(gè)特性,在其他應(yīng)用場(chǎng)景中非常有用,而在現(xiàn)在的計(jì)算機(jī)硬件條件下,用來(lái)加密密碼就顯得不合適了。針對(duì)這一點(diǎn),密碼學(xué)家們?cè)O(shè)計(jì)了PBKDF2、BCRYPT、SCRYPT等用來(lái)加密密碼的Hash算法,稱作Password Hash。在他們的算法內(nèi)部,通常都需要計(jì)算Cryptographic Hash很多次,從而減慢Hash的計(jì)算速度,增大黑客暴力破解的成本。可以說(shuō)Password Hash有一條設(shè)計(jì)原則,就是計(jì)算過(guò)程能夠按要求變慢,并且不容易被硬件加速。

應(yīng)該使用哪一種Password Hash?

PBKDF2、BCRYPT、SCRYPT曾經(jīng)是最常用的三種密碼Hash算法,至于哪種算法最好,多年以來(lái)密碼學(xué)家們并無(wú)定論。但可以確定的是,這三種算法都不完美,各有缺點(diǎn)。其中PBKDF2因?yàn)橛?jì)算過(guò)程需要內(nèi)存少所以可被GPU/ASIC加速,BCRYPT不支持內(nèi)存占用調(diào)整且容易被FPGA加速,而SCRYPT不支持單獨(dú)調(diào)整內(nèi)存或計(jì)算時(shí)間占用且可能被ASIC加速并有被旁路攻擊的可能。

2013年NIST(美國(guó)國(guó)家標(biāo)準(zhǔn)與技術(shù)研究院)邀請(qǐng)了一些密碼學(xué)家一起,舉辦了密碼hash算法大賽(Password Hashing Competition),意在尋找一種標(biāo)準(zhǔn)的用來(lái)加密密碼的hash算法,并借此在業(yè)界宣傳加密存儲(chǔ)用戶密碼的重要性。大賽列出了參賽算法可能面臨的攻擊手段:

加密算法破解(原值還原、哈希碰撞等,即應(yīng)滿足Cryptographic Hash的第2、3、4條特性);

查詢表/彩虹表攻擊;

CPU優(yōu)化攻擊;

GPU、FPGA、ASIC等專用硬件攻擊;

旁路攻擊;

最終在2015年7月,Argon2算法贏得了這項(xiàng)競(jìng)賽,被NIST認(rèn)定為最好的密碼hash算法。不過(guò)因?yàn)樗惴ㄟ^(guò)新,目前還沒(méi)聽(tīng)說(shuō)哪家大公司在用Argon2做密碼加密。

一路問(wèn)過(guò)來(lái)好累,能不能給我舉個(gè)例子,大公司是怎么加密用戶密碼的?

今年(2016)Dropbox曾發(fā)生部分用戶密碼數(shù)據(jù)泄露事件,當(dāng)時(shí)其CTO表示他們對(duì)自己加密密碼的方式很有信心,請(qǐng)用戶放心。隨后,Dropbox在其官方技術(shù)博客發(fā)表名為《How Dropbox securely stores your passwords》的文章,講述了他們的用戶密碼加密存儲(chǔ)方案。

如上圖所示,Dropbox首先對(duì)用戶密碼做了一次sha512哈希將密碼轉(zhuǎn)化為64個(gè)字節(jié),然后對(duì)sha512的結(jié)果使用Bcrypt算法(每個(gè)用戶獨(dú)立的鹽、強(qiáng)度為10)計(jì)算,最后使用AES算法和全局唯一的密鑰將Bcrypt算法的計(jì)算結(jié)果加密并保存。

博文中,Dropbox描述了這三層加密的原因:

首先使用sha512,將用戶密碼歸一化為64字節(jié)hash值。因?yàn)閮蓚€(gè)原因:一個(gè)是Bcrypt算對(duì)輸入敏感,如果用戶輸入的密碼較長(zhǎng),可能導(dǎo)致Bcrypt計(jì)算過(guò)慢從而影響響應(yīng)時(shí)間;另一個(gè)是有些Bcrypt算法的實(shí)現(xiàn)會(huì)將長(zhǎng)輸入直接截?cái)酁?2字節(jié),從信息論的角度講,這導(dǎo)致用戶信息的熵變?。?/p>

然后使用Bcrypt算法。選擇Bcrypt的原因,是Dropbox的工程師對(duì)這個(gè)算法更熟悉調(diào)優(yōu)更有經(jīng)驗(yàn),參數(shù)選擇的標(biāo)準(zhǔn),是Dropbox的線上API服務(wù)器可以在100ms左右的時(shí)間可計(jì)算出結(jié)果。另外,關(guān)于Bcrypt和Scrypt哪個(gè)算法更優(yōu),密碼學(xué)家也沒(méi)有定論。同時(shí),Dropbox也在關(guān)注密碼hash算法新秀Argon2,并表示會(huì)在合適的時(shí)機(jī)引入;

最后使用AES加密。因?yàn)锽crypt不是完美的算法,所以Dropbox使用AES和全局密鑰進(jìn)一步降低密碼被破解的風(fēng)險(xiǎn),為了防止密鑰泄露,Dropbox采用了專用的密鑰保存硬件。Dropbox還提到了最后使用AES加密的另一個(gè)好處,即密鑰可定時(shí)更換,以降低用戶信息/密鑰泄露帶來(lái)的風(fēng)險(xiǎn)。

THEEND

最新評(píng)論(評(píng)論僅代表用戶觀點(diǎn))

更多
暫無(wú)評(píng)論