久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

如何安全的存儲(chǔ)用戶(hù)密碼?

 StephenCSP 2017-03-13
作者|Defuse Security團(tuán)隊(duì)
編輯|劉志勇

本文介紹了對(duì)密碼哈希加密的基礎(chǔ)知識(shí),,以及什么是正確的加密方式,。還介紹了常見(jiàn)的密碼破解方法,給出了如何避免密碼被破解的思路,。相信讀者閱讀本文后,,就會(huì)對(duì)密碼的加密有一個(gè)正確的認(rèn)識(shí),并對(duì)密碼正確進(jìn)行加密措施,。

本文由Defuse Security安全團(tuán)隊(duì)撰寫(xiě),,作者采用了 CC協(xié)議 ,InfoQ翻譯并分享,,以饗讀者,。

作為一名Web開(kāi)發(fā)人員,我們經(jīng)常需要與用戶(hù)的賬號(hào)系統(tǒng)打交道,,而這其中最大的挑戰(zhàn)就是如何保護(hù)用戶(hù)的密碼,。經(jīng)常會(huì)看到用戶(hù)賬戶(hù)數(shù)據(jù)庫(kù)頻繁被黑,所以我們必須采取一些措施來(lái)保護(hù)用戶(hù)密碼,,以免導(dǎo)致不必要的數(shù)據(jù)泄露,。保護(hù)密碼的最好辦法是使用加鹽密碼哈希( salted password hashing)。

在對(duì)密碼進(jìn)行哈希加密的問(wèn)題上,,人們有很多爭(zhēng)論和誤解,,可能是由于網(wǎng)絡(luò)上有大量錯(cuò)誤信息的原因吧。對(duì)密碼哈希加密是一件很簡(jiǎn)單的事,,但很多人都犯了錯(cuò),。本文將會(huì)重點(diǎn)分享如何進(jìn)行正確加密用戶(hù)密碼。

重要警告:請(qǐng)放棄編寫(xiě)自己的密碼哈希加密代碼的念頭,!因?yàn)檫@件事太容易搞砸了,。就算你在大學(xué)學(xué)過(guò)密碼學(xué)的知識(shí),也應(yīng)該遵循這個(gè)警告,。所有人都要謹(jǐn)記這點(diǎn):不要自己寫(xiě)哈希加密算法,! 存儲(chǔ)密碼的相關(guān)問(wèn)題已經(jīng)有了成熟的解決方案,,就是使用 phpass,或者在 defuse/password-hashinglibsodium 上的 PHP ,、 C# ,、 Java 和 Ruby 的實(shí)現(xiàn)。

密碼哈希是什么,?

哈希算法是一種單向函數(shù),。它把任意數(shù)量的數(shù)據(jù)轉(zhuǎn)換為固定長(zhǎng)度的“指紋”,而且這個(gè)過(guò)程無(wú)法逆轉(zhuǎn),。它們有這樣的特性:如果輸入發(fā)生了一點(diǎn)改變,,由此產(chǎn)生的哈希值會(huì)完全不同(參見(jiàn)上面的例子)。這個(gè)特性很適合用來(lái)存儲(chǔ)密碼,。因?yàn)槲覀冃枰环N不可逆的算法來(lái)加密存儲(chǔ)的密碼,,同時(shí)保證我們也能夠驗(yàn)證用戶(hù)登陸的密碼是否正確。

在基于哈希加密的賬號(hào)系統(tǒng)中,,用戶(hù)注冊(cè)和認(rèn)證的大致流程如下,。

  1. 用戶(hù)創(chuàng)建自己的賬號(hào)。

  2. 密碼經(jīng)過(guò)哈希加密后存儲(chǔ)在數(shù)據(jù)庫(kù)中,。密碼一旦寫(xiě)入到磁盤(pán),,任何時(shí)候都不允許是明文形式。

  3. 當(dāng)用戶(hù)試圖登錄時(shí),,系統(tǒng)從數(shù)據(jù)庫(kù)取出已經(jīng)加密的密碼,,和經(jīng)過(guò)哈希加密的用戶(hù)輸入的密碼進(jìn)行對(duì)比。

  4. 如果哈希值相同,,用戶(hù)將被授予訪(fǎng)問(wèn)權(quán)限,。否則,告知用戶(hù)他們輸入的登陸憑據(jù)無(wú)效,。

  5. 每當(dāng)有人試圖嘗試登陸,,就重復(fù)步驟3和4。

在步驟4中,,永遠(yuǎn)不要告訴用戶(hù)輸錯(cuò)的究竟是用戶(hù)名還是密碼,。就像通用的提示那樣,始終顯示:“無(wú)效的用戶(hù)名或密碼,?!本托辛恕_@樣可以防止攻擊者在不知道密碼的情況下枚舉出有效的用戶(hù)名,。

應(yīng)當(dāng)注意的是,,用來(lái)保護(hù)密碼的哈希函數(shù),和數(shù)據(jù)結(jié)構(gòu)課學(xué)到的哈希函數(shù)是不同的,。例如,,實(shí)現(xiàn)哈希表的哈希函數(shù)設(shè)計(jì)目的是快速查找,,而非安全性。只有加密哈希函數(shù)( cryptographic hash function)才可以用來(lái)進(jìn)行密碼哈希加密,。像 SHA256 ,、 SHA512 、 RIPEMD 和 WHIRLPOOL 都是加密哈希函數(shù),。

人們很容易認(rèn)為,,Web開(kāi)發(fā)人員所做的就是:只需通過(guò)執(zhí)行加密哈希函數(shù)就可以讓用戶(hù)密碼得以安全。然而并不是這樣,。有很多方法可以從簡(jiǎn)單的哈希值中快速恢復(fù)出明文的密碼。有幾種易于實(shí)施的技術(shù),,使這些“破解”的效率大為降低,。網(wǎng)上有這種專(zhuān)門(mén)破解MD5的網(wǎng)站,只需提交一個(gè)哈希值,,不到一秒鐘就能得到破解的結(jié)果,。顯然,,單純的對(duì)密碼進(jìn)行哈希加密遠(yuǎn)遠(yuǎn)達(dá)不到我們的安全要求,。下一節(jié)將討論一些用來(lái)破解簡(jiǎn)單密碼哈希常用的手段。

如何破解哈希,?
字典攻擊和暴力攻擊( Dictionary and Brute Force Attacks)
字典攻擊暴力攻擊
Trying apple        : failedTrying aaaa : failed
Trying blueberry    : failedTrying aaab : failed
Trying justinbeiber : failedTrying aaac : failed
Trying letmein      : failedTrying acdb : failed
Trying s3cr3t       : success!Trying acdc : success!

破解哈希加密最簡(jiǎn)單的方法是嘗試猜測(cè)密碼,,哈希每個(gè)猜測(cè)的密碼,并對(duì)比猜測(cè)密碼的哈希值是否等于被破解的哈希值,。如果相等,,則猜中。猜測(cè)密碼攻擊的兩種最常見(jiàn)的方法是字典攻擊和暴力攻擊 ,。

字典攻擊使用包含單詞,、短語(yǔ)、常用密碼和其他可能用做密碼的字符串的字典文件,。對(duì)文件中的每個(gè)詞都進(jìn)行哈希加密,,將這些哈希值和要破解的密碼哈希值比較。如果它們相同,,這個(gè)詞就是密碼,。字典文件是通過(guò)大段文本中提取的單詞構(gòu)成,甚至還包括一些數(shù)據(jù)庫(kù)中真實(shí)的密碼,。還可以對(duì)字典文件進(jìn)一步處理以使其更為有效:如單詞 “hello” 按網(wǎng)絡(luò)用語(yǔ)寫(xiě)法轉(zhuǎn)成 “h3110” ,。

暴力攻擊是對(duì)于給定的密碼長(zhǎng)度,嘗試每一種可能的字符組合,。這種方式會(huì)消耗大量的計(jì)算,,也是破解哈希加密效率最低的辦法,,但最終會(huì)找出正確的密碼。因此密碼應(yīng)該足夠長(zhǎng),,以至于遍歷所有可能的字符組合,,耗費(fèi)的時(shí)間太長(zhǎng)令人無(wú)法承受,從而放棄破解,。

目前沒(méi)有辦法來(lái)組織字典攻擊或暴力攻擊,。只能想辦法讓它們變得低效。如果密碼哈希系統(tǒng)設(shè)計(jì)是安全的,,破解哈希的唯一方法就是進(jìn)行字典攻擊或暴力攻擊遍歷每一個(gè)哈希值了,。

查表法( Lookup Tables)
Searching: 5f4dcc3b5aa765d61d8327deb882cf99: FOUND: password5Searching: 6cbe615c106f422d23669b610b564800:  not in databaseSearching: 630bf032efe4507f2c57b280995925a9: FOUND: letMEin12 Searching: 386f43fab5d096a7a66d67c8f213e5ec: FOUND: mcd0naldsSearching: d5ec75d5fe70d428685510fae36492d9: FOUND: p@ssw0rd!

對(duì)于破解相同類(lèi)型的哈希值,查表法是一種非常高效的方式,。主要理念是預(yù)先計(jì)算( pre-compute)出密碼字典中的每個(gè)密碼的哈希值,,然后把他們相應(yīng)的密碼存儲(chǔ)到一個(gè)表里。一個(gè)設(shè)計(jì)良好的查詢(xún)表結(jié)構(gòu),,即使包含了數(shù)十億個(gè)哈希值,,仍然可以實(shí)現(xiàn)每秒鐘查詢(xún)數(shù)百次哈希。

如果你想感受查表法的速度有多快,,嘗試一下用 CrackStation 的 free hash cracker 來(lái)破解下面的 SHA256,。

反向查表法( Reverse Lookup Tabs)

這種攻擊允許攻擊者無(wú)需預(yù)先計(jì)算好查詢(xún)表的情況下同時(shí)對(duì)多個(gè)哈希值發(fā)起字典攻擊或暴力攻擊。

首先,,攻擊者從被黑的用戶(hù)賬號(hào)數(shù)據(jù)庫(kù)創(chuàng)建一個(gè)用戶(hù)名和對(duì)應(yīng)的密碼哈希表,,然后,攻擊者猜測(cè)一系列哈希值并使用該查詢(xún)表來(lái)查找使用此密碼的用戶(hù),。通常許多用戶(hù)都會(huì)使用相同的密碼,,因此這種攻擊方式特別有效。

彩虹表( Rainbow Tables)

彩虹表是一種以空間換時(shí)間的技術(shù),。與查表法相似,,只是它為了使查詢(xún)表更小,犧牲了破解速度,。因?yàn)椴屎绫砀?,所以在單位空間可以存儲(chǔ)更多的哈希值,從而使攻擊更有效,。能夠破解任何最多8位長(zhǎng)度的 MD5 值的彩虹表已經(jīng)出現(xiàn),。

接下來(lái),我們來(lái)看一種謂之“加鹽( salting)”的技術(shù),,能夠讓查表法和彩虹表都失效,。

加鹽( Adding Salt)

查表法和彩虹表只有在所有密碼都以完全相同的方式進(jìn)行哈希加密才有效。如果兩個(gè)用戶(hù)有相同的密碼,,他們將有相同的密碼哈希值,。我們可以通過(guò)“隨機(jī)化”哈希,,當(dāng)同一個(gè)密碼哈希兩次后,得到的哈希值是不一樣的,,從而避免了這種攻擊,。

我們可以通過(guò)在密碼中加入一段隨機(jī)字符串再進(jìn)行哈希加密,這個(gè)被加的字符串稱(chēng)之為鹽值,。如上例所示,,這使得相同的密碼每次都被加密為完全不同的字符串。我們需要鹽值來(lái)校驗(yàn)密碼是否正確,。通常和密碼哈希值一同存儲(chǔ)在賬號(hào)數(shù)據(jù)庫(kù)中,,或者作為哈希字符串的一部分。

鹽值無(wú)需加密,。由于隨機(jī)化了哈希值,,查表法、反向查表法和彩虹表都會(huì)失效,。因?yàn)楣粽邿o(wú)法事先知道鹽值,,所以他們就沒(méi)有辦法預(yù)先計(jì)算查詢(xún)表或彩虹表,。如果每個(gè)用戶(hù)的密碼用不同的鹽再進(jìn)行哈希加密,,那么反向查表法攻擊也將不能奏效。

接下來(lái),,我們看看加鹽哈希通常會(huì)有哪些不正確的措施,。

錯(cuò)誤的方法:短鹽值和鹽值復(fù)用

最常見(jiàn)的錯(cuò)誤,是多次哈希加密使用相同的鹽值,,或者鹽值太短,。

鹽值復(fù)用( Salt Reuse)

一個(gè)常見(jiàn)的錯(cuò)誤是每次都使用相同的鹽值進(jìn)行哈希加密,這個(gè)鹽值要么被硬編碼到程序里,,要么只在第一次使用時(shí)隨機(jī)獲得,。這樣的做法是無(wú)效的,因?yàn)槿绻麅蓚€(gè)用戶(hù)有相同的密碼,,他們?nèi)匀粫?huì)有相同的哈希值。攻擊者仍然可以使用反向查表法對(duì)每個(gè)哈希值進(jìn)行字典攻擊,。他們只是在哈希密碼之前,,將固定的鹽值應(yīng)用到每個(gè)猜測(cè)的密碼就可以了。如果鹽值被硬編碼到一個(gè)流行的軟件里,,那么查詢(xún)表和彩虹表可以?xún)?nèi)置該鹽值,,以使其更容易破解它產(chǎn)生的哈希值。

用戶(hù)創(chuàng)建賬號(hào)或者更改密碼時(shí),,都應(yīng)該用新的隨機(jī)鹽值進(jìn)行加密,。

短鹽值( Short Slat)

如果鹽值太短,,攻擊者可以預(yù)先制作針對(duì)所有可能的鹽值的查詢(xún)表。例如,,如果鹽值只有三個(gè) ASCII 字符,,那么只有 95x95x95=857,375種可能性。這看起來(lái)很多,,但如果每個(gè)查詢(xún)表包含常見(jiàn)的密碼只有 1MB,,857,375個(gè)鹽值總共只需 837GB,一塊時(shí)下不到100美元的 1TB硬盤(pán)就能解決問(wèn)題了,。

出于同樣的原因,,不應(yīng)該將用戶(hù)名用作鹽值。對(duì)每一個(gè)服務(wù)來(lái)說(shuō),,用戶(hù)名是唯一的,,但它們是可預(yù)測(cè)的,并且經(jīng)常重復(fù)應(yīng)用于其他服務(wù),。攻擊者可以用常見(jiàn)用戶(hù)名作為鹽值來(lái)建立查詢(xún)表和彩虹表來(lái)破解密碼哈希,。

為使攻擊者無(wú)法構(gòu)造包含所有可能鹽值的查詢(xún)表,鹽值必須足夠長(zhǎng),。一個(gè)好的經(jīng)驗(yàn)是使用和哈希函數(shù)輸出的字符串等長(zhǎng)的鹽值,。例如, SHA256 的輸出為256位(32字節(jié)),,所以該鹽也應(yīng)該是32個(gè)隨機(jī)字節(jié),。

雙重哈希和古怪的哈希函數(shù)

本節(jié)將介紹另一種常見(jiàn)的密碼哈希的誤解:古怪哈希的算法組合。人們很容易沖昏頭腦,,嘗試不同的哈希函數(shù)相結(jié)合一起使用,,希望讓數(shù)據(jù)會(huì)更安全。但在實(shí)踐中,,這樣做并沒(méi)有什么好處,。它帶來(lái)了函數(shù)之間互通性的問(wèn)題,而且甚至可能會(huì)使哈希變得更不安全,。永遠(yuǎn)不要試圖去創(chuàng)造你自己的哈希加密算法,,要使用專(zhuān)家設(shè)計(jì)好的標(biāo)準(zhǔn)算法。有人會(huì)說(shuō),,使用多個(gè)哈希函數(shù)會(huì)降低計(jì)算速度,,從而增加破解的難度。但是使破解過(guò)程變慢還有更好的辦法,,我們將在后面講到,。

下面是在網(wǎng)上見(jiàn)過(guò)的古怪的哈希函數(shù)組合的一些例子。

  • md5(sha1(password))

  • md5(md5(salt) + md5(password))

  • sha1(sha1(password))

  • sha1(str_rot13(password + salt))

  • md5(sha1(md5(md5(password) + sha1(password)) + md5(password))))

不要使用其中任何一種。

注意:此部分是有爭(zhēng)議的,。我收到了一些電子郵件,,他們認(rèn)為古怪的哈希函數(shù)是有意義的,理由是,,如果攻擊者不知道系統(tǒng)使用哪個(gè)哈希函數(shù),,那么攻擊者就不太可能預(yù)先計(jì)算出這種古怪的哈希函數(shù)彩虹表,于是破解起來(lái)要花更多的時(shí)間,。

當(dāng)攻擊者不知道哈希加密算法的時(shí)候,,是無(wú)法發(fā)起攻擊的。但是要考慮到柯克霍夫原則,,攻擊者通常會(huì)獲得源代碼(尤其是免費(fèi)或者開(kāi)源軟件),。通過(guò)系統(tǒng)中找出密碼-哈希值對(duì)應(yīng)關(guān)系,很容易反向推導(dǎo)出加密算法,。使用一個(gè)很難被并行計(jì)算結(jié)果的迭代算法(下面將予以討論),,然后增加適當(dāng)?shù)柠}值防止彩虹表攻擊。

如果你真的想用一個(gè)標(biāo)準(zhǔn)的“古怪”的哈希函數(shù),,如 HMAC ,,亦無(wú)不可。但是,,如果你目的是想降低哈希計(jì)算速度,,那么可以閱讀下面有關(guān)密鑰擴(kuò)展的部分。

如果創(chuàng)造新的哈希函數(shù),,可能會(huì)帶來(lái)風(fēng)險(xiǎn),,構(gòu)造希函數(shù)的組合又會(huì)導(dǎo)致函數(shù)互通性的問(wèn)題,。它們帶來(lái)一點(diǎn)的好處和這些比起來(lái)微不足道,。很顯然,最好的辦法是,,使用標(biāo)準(zhǔn),、經(jīng)過(guò)完整測(cè)試的算法。

哈希碰撞( Hash Collisions)

由于哈希函數(shù)將任意大小的數(shù)據(jù)轉(zhuǎn)化為定長(zhǎng)的字符串,,因此,,必定有一些不同的輸入經(jīng)過(guò)哈希計(jì)算后得到了相同的字符串的情況。加密哈希函數(shù)( Cryptographic hash function)的設(shè)計(jì)初衷就是使這些碰撞盡量難以被找到?,F(xiàn)在,,密碼學(xué)家發(fā)現(xiàn)攻擊哈希函數(shù)越來(lái)越容易找到碰撞了。最近的例子是MD5算法,,它的碰撞已經(jīng)實(shí)現(xiàn)了,。

碰撞攻擊是指存在一個(gè)和用戶(hù)密碼不同的字符串,卻有相同的哈希值。然而,,即使是像MD5這樣的脆弱的哈希函數(shù)找到碰撞也需要大量的專(zhuān)門(mén)算力( dedicated computing power),,所以在實(shí)際中“意外地”出現(xiàn)哈希碰撞的情況不太可能。對(duì)于實(shí)用性而言,,加鹽 MD5 和加鹽 SHA256 的安全性一樣,。盡管如此,可能的話(huà),,要使用更安全的哈希函數(shù),,比如 SHA256 、 SHA512 ,、 RipeMD 或 WHIRLPOOL ,。

如何正確進(jìn)行哈希加密

本節(jié)介紹了究竟應(yīng)該如何對(duì)密碼進(jìn)行哈希加密。第一部分介紹基礎(chǔ)知識(shí),,這部分是必須的,。后面闡述如何在這個(gè)基礎(chǔ)上增強(qiáng)安全性,使哈希加密變得更難破解,。

基礎(chǔ)知識(shí):加鹽哈希( Hashing with Salt)

我們已經(jīng)知道,,惡意攻擊者使用查詢(xún)表和彩虹表,破解普通哈希加密有多么快,。我們也已經(jīng)了解到,,使用隨機(jī)加鹽哈希可以解決這個(gè)問(wèn)題,。但是,,我們使用什么樣的鹽值,又如何將其混入密碼中,?

鹽值應(yīng)該使用加密的安全偽隨機(jī)數(shù)生成器( Cryptographically Secure Pseudo-Random Number Generator,,CSPRNG )產(chǎn)生。CSPRNG和普通的偽隨機(jī)數(shù)生成器有很大不同,,如“ C ”語(yǔ)言的rand()函數(shù),。顧名思義, CSPRNG 被設(shè)計(jì)成用于加密安全,,這意味著它能提供高度隨機(jī),、完全不可預(yù)測(cè)的隨機(jī)數(shù)。我們不希望鹽值能夠被預(yù)測(cè)到,,所以必須使用 CSPRNG ,。下表列出了一些當(dāng)前主流編程平臺(tái)的 CSPRNG 方法。

PlatformCSPRNG
PHPmcrypt_create_iv, openssl_random_pseudo_bytes
Javajava.security.SecureRandom
Dot NET (C#, VB)System.Security.Cryptography.RNGCryptoServiceProvider
RubySecureRandom
Pythonos.urandom
PerlMath::Random::Secure
C/C++ (Windows API)CryptGenRandom
Any language on GNU/Linux or UnixRead from /dev/random or /dev/urandom

每個(gè)用戶(hù)的每一個(gè)密碼都要使用獨(dú)一無(wú)二的鹽值,。用戶(hù)每次創(chuàng)建賬號(hào)或更改密碼時(shí),,密碼應(yīng)采用一個(gè)新的隨機(jī)鹽值。永遠(yuǎn)不要重復(fù)使用某個(gè)鹽值。這個(gè)鹽值也應(yīng)該足夠長(zhǎng),,以使有足夠多的鹽值能用于哈希加密,。一個(gè)經(jīng)驗(yàn)規(guī)則是,鹽值至少要跟哈希函數(shù)的輸出一樣長(zhǎng),。該鹽應(yīng)和密碼哈希一起存儲(chǔ)在用戶(hù)賬號(hào)表中,。

存儲(chǔ)密碼的步驟:

  1. 使用 CSPRNG 生成足夠長(zhǎng)的隨機(jī)鹽值。

  2. 將鹽值混入密碼,,并使用標(biāo)準(zhǔn)的密碼哈希函數(shù)進(jìn)行加密,,如Argon2、 bcrypt ,、 scrypt 或 PBKDF2 ,。

  3. 將鹽值和對(duì)應(yīng)的哈希值一起存入用戶(hù)數(shù)據(jù)庫(kù)。

校驗(yàn)密碼的步驟:

  1. 從數(shù)據(jù)庫(kù)檢索出用戶(hù)的鹽值和對(duì)應(yīng)的哈希值,。

  2. 將鹽值混入用戶(hù)輸入的密碼,并且使用通用的哈希函數(shù)進(jìn)行加密,。

  3. 比較上一步的結(jié)果,,是否和數(shù)據(jù)庫(kù)存儲(chǔ)的哈希值相同。如果它們相同,,則表明密碼是正確的,;否則,該密碼錯(cuò)誤,。

在 Web 應(yīng)用中,,永遠(yuǎn)在服務(wù)端上進(jìn)行哈希加密

如果您正在編寫(xiě)一個(gè) Web 應(yīng)用,你可能會(huì)疑惑究竟在哪里進(jìn)行哈希加密,,是在用戶(hù)的瀏覽器上使用 JavaScript 對(duì)密碼進(jìn)行哈希加密呢,,還是將明文發(fā)送到服務(wù)端上再進(jìn)行哈希加密呢?

就算瀏覽器上已經(jīng)用JavaScript哈希加密了,,但你你還是要在服務(wù)端上將得到的密碼哈希值再進(jìn)行一次哈希加密,。試想一個(gè)網(wǎng)站,,將用戶(hù)在瀏覽器輸入的密碼經(jīng)過(guò)哈希加密,,而不是在傳送到服務(wù)端再進(jìn)行哈希。為了驗(yàn)證用戶(hù),,這個(gè)網(wǎng)站將接受來(lái)自瀏覽器的哈希值,,并和數(shù)據(jù)庫(kù)中的哈希值進(jìn)行匹配即可。因?yàn)橛脩?hù)的密碼從未明文傳輸?shù)椒?wù)端,,這樣子看上去更安全,,但事實(shí)并非如此。

問(wèn)題是,從客戶(hù)端的角度來(lái)看,,經(jīng)過(guò)哈希的密碼,,從邏輯上成為用戶(hù)的密碼了。所有用戶(hù)需要做的認(rèn)證就是將它們的密碼哈希值告訴服務(wù)端,。如果一個(gè)攻擊者得到了用戶(hù)的哈希值,,他們可以用它來(lái)通過(guò)認(rèn)證,而不必知道用戶(hù)的明文密碼,!所以,,如果攻擊者使用某種手段拖了網(wǎng)站的數(shù)據(jù)庫(kù),他們就可以隨意使用每個(gè)人的賬號(hào)直接訪(fǎng)問(wèn),,而無(wú)需猜測(cè)任何密碼,。

這并不是說(shuō)你不應(yīng)該在瀏覽器進(jìn)行哈希加密,但是如果你這樣做了,,你一定要在服務(wù)端上再進(jìn)行一次哈希加密,。在瀏覽器中進(jìn)行哈希加密無(wú)疑是一個(gè)好主意,但實(shí)現(xiàn)的時(shí)候要考慮以下幾點(diǎn):

  • 客戶(hù)端密碼哈希加密不是 HTTPS(SSL/TLS)的替代品,。如果瀏覽器和服務(wù)端之間的連接是不安全的,,那么中間人攻擊可以修改 JavaScript 代碼,刪除加密函數(shù),,從而獲取用戶(hù)的密碼,。

  • 某些瀏覽器不支持 JavaScript ,還有一些用戶(hù)在瀏覽器中禁用 JavaScript 功能,。因此,,為了更好的兼容性,您的應(yīng)用應(yīng)該檢測(cè)瀏覽器是否支持 JavaScript ,,如果不支持,,就需要在服務(wù)端模擬客戶(hù)端進(jìn)行哈希加密。

  • 客戶(hù)端的哈希加密同樣需要加鹽,。顯而易見(jiàn)的解決方案是使客戶(hù)端腳本向服務(wù)端請(qǐng)求用戶(hù)的鹽值,。但是不提倡這樣做,因?yàn)樗梢宰尮粽吣軌蛟诓恢烂艽a的情況下檢測(cè)用戶(hù)名是否有效,。既然你已經(jīng)在服務(wù)端上對(duì)密碼進(jìn)行了加鹽哈希(使用合格的鹽值),,那么在客戶(hù)端,將用戶(hù)名(或郵箱)加上網(wǎng)站特有的字符串(如域名)作為客戶(hù)端的鹽值也是可行的,。

使密碼更難破解:慢哈希函數(shù)( Slow Hash Function)

加鹽可以確保攻擊者無(wú)法使用像查詢(xún)表和彩虹表攻擊那樣對(duì)大量哈希值進(jìn)行破解,,但依然不能阻止他們使用字典攻擊或暴力攻擊。高端顯卡( GPU )和定制的硬件每秒可以進(jìn)行十億次哈希計(jì)算,,所以這些攻擊還是很有效的,。為了降低使這些攻擊的效率,,我們可以使用一個(gè)叫做密鑰擴(kuò)展( key stretching)的技術(shù)。

這樣做的初衷是為了將哈希函數(shù)變得非常慢,,即使有一塊快速的 GPU 或定制的硬件,,字典攻擊和暴力攻擊也會(huì)慢得令人失去耐心。終極目標(biāo)是使哈希函數(shù)的速度慢到足以令攻擊者放棄,,但由此造成的延遲又不至于引起用戶(hù)的注意,。

密鑰擴(kuò)展的實(shí)現(xiàn)使用了一種 CPU 密集型哈希函數(shù)( CPU-intensive hash function)。不要試圖去創(chuàng)造你自己的迭代哈希加密函數(shù),。迭代不夠多的話(huà),,它可以被高效的硬件快速并行計(jì)算出來(lái),就跟普通的哈希一樣,。要使用標(biāo)準(zhǔn)的算法,,比如 PBKDF2 或 bcrypt 。你可以在這里找到 PBKDF2 在 PHP 上的實(shí)現(xiàn),。

這類(lèi)算法采取安全因子或迭代次數(shù)作為參數(shù),。此值決定哈希函數(shù)將會(huì)如何緩慢。對(duì)于桌面軟件或智能手機(jī)應(yīng)用,,確定這個(gè)參數(shù)的最佳方式是在設(shè)備上運(yùn)行很短的性能基準(zhǔn)測(cè)試,,找到使哈希大約花費(fèi)半秒的值。通過(guò)這種方式,,程序可以盡可能保證安全而又不影響用戶(hù)體驗(yàn),。

如果您想在一個(gè) Web 應(yīng)用使用密鑰擴(kuò)展,須知你需要額外的計(jì)算資源來(lái)處理大量的身份認(rèn)證請(qǐng)求,,并且密鑰擴(kuò)展也容易讓服務(wù)端遭受拒絕服務(wù)攻擊( DoS ),。盡管如此,我還是建議使用密鑰擴(kuò)展,,只不過(guò)要設(shè)定較低一些的迭代次數(shù),。這個(gè)次數(shù)需要根據(jù)自己服務(wù)器的計(jì)算能力和預(yù)計(jì)每秒需要處理的認(rèn)證請(qǐng)求次數(shù)來(lái)設(shè)置。消除拒絕服務(wù)的威脅可以通過(guò)要求用戶(hù)每次登陸時(shí)輸入驗(yàn)證碼( CAPTCHA )來(lái)做到,。系統(tǒng)設(shè)計(jì)時(shí)要將迭代次數(shù)可隨時(shí)方便調(diào)整,。

如果你擔(dān)心計(jì)算帶來(lái)負(fù)擔(dān),但又想在 Web 應(yīng)用中使用密鑰擴(kuò)展,,可以考慮在瀏覽器中使用 JavaScript 完成,。斯坦福大學(xué)的 JavaScript 加密庫(kù)就包含了 PBKDF2 的實(shí)現(xiàn)。迭代次數(shù)應(yīng)設(shè)置足夠低,,以適應(yīng)速度較慢的客戶(hù)端,,如移動(dòng)設(shè)備。同時(shí),,如果用戶(hù)的瀏覽器不支持 JavaScript ,,服務(wù)端應(yīng)該接手進(jìn)行計(jì)算??蛻?hù)端密鑰擴(kuò)展并不能免除服務(wù)端端進(jìn)行哈希加密的需要,。你必須對(duì)客戶(hù)端生成的哈希值再次進(jìn)行哈希加密,就跟普通口令的處理一樣,。

不可能破解的哈希加密:密鑰哈希和密碼哈希設(shè)備

只要攻擊者可以使用哈希來(lái)檢查密碼的猜測(cè)是對(duì)還是錯(cuò),,那么他們可以進(jìn)行字典攻擊或暴力攻擊。下一步是將密鑰( secret key)添加到哈希加密,,這樣只有知道密鑰的人才可以驗(yàn)證密碼,。有兩種實(shí)現(xiàn)的方式,使用ASE算法對(duì)哈希值加密,;或者使用密鑰哈希算法 HMAC 將密鑰包含到哈希字符串中,。

實(shí)現(xiàn)起來(lái)并沒(méi)那么容易。這個(gè)密鑰必須在任何情況下,,即使系統(tǒng)因?yàn)槁┒幢还ハ?,也不能被攻擊者獲取。如果攻擊者完全進(jìn)入系統(tǒng),,密鑰不管存儲(chǔ)在何處,,總能被找到。因此,,密鑰必須密鑰必須被存儲(chǔ)在外部系統(tǒng),,例如專(zhuān)用于密碼驗(yàn)證一個(gè)物理上隔離的服務(wù)端,或者連接到服務(wù)端,,例如一個(gè)特殊的硬件設(shè)備,,如 YubiHSM

我強(qiáng)烈建議所有大型服務(wù)(超過(guò)10萬(wàn)用戶(hù))使用這種方式,。我認(rèn)為對(duì)于任何超過(guò)100萬(wàn)用戶(hù)的服務(wù)托管是非常有必要的,。

如果您難以負(fù)擔(dān)多個(gè)服務(wù)端或?qū)S糜布馁M(fèi)用,依然有辦法在標(biāo)準(zhǔn)的Web服務(wù)端上使用密鑰哈希技術(shù),。大多數(shù)數(shù)據(jù)庫(kù)被拖庫(kù)是由于 SQL 注入攻擊,,因此,不要給攻擊者進(jìn)入本地文件系統(tǒng)的權(quán)限(禁止數(shù)據(jù)庫(kù)服務(wù)訪(fǎng)問(wèn)本地文件系統(tǒng),,如果有此功能的話(huà)),。如果您生成一個(gè)隨機(jī)密鑰并將其存儲(chǔ)在一個(gè)通過(guò) Web 無(wú)法訪(fǎng)問(wèn)的文件上,然后進(jìn)行加鹽哈希加密,,那么得到的哈希值就不會(huì)那么容易被破解了,,就算數(shù)據(jù)庫(kù)已經(jīng)遭受注入攻擊,也是安全的,。不要將密鑰硬編碼到代碼中,,應(yīng)該在安裝應(yīng)用時(shí)隨機(jī)生成,。這么做并不像使用一個(gè)獨(dú)立的系統(tǒng)那樣安全,因?yàn)槿绻?Web 應(yīng)用存在 SQL 注入點(diǎn),,那么有可能存在其他一些問(wèn)題,,如本地文件包含漏洞( Local File Inclusion ),攻擊者可以利用它讀取本地密鑰文件,。無(wú)論如何,,這個(gè)措施總比沒(méi)有好。

請(qǐng)注意,,密鑰哈希并不意味著無(wú)需進(jìn)行加鹽,。高明的攻擊者最終會(huì)想方設(shè)法找到密鑰,因此,,對(duì)密碼哈希仍然需要進(jìn)行加鹽和密鑰擴(kuò)展,,這一點(diǎn)非常重要。

其他安全措施

密碼哈希僅僅在安全受到破壞時(shí)保護(hù)密碼,。它并不能使整個(gè)應(yīng)用更加安全,。首先有很多事必須完成,來(lái)保證密碼哈希值(和其他用戶(hù)數(shù)據(jù))不被竊取,。

即使是經(jīng)驗(yàn)豐富的開(kāi)發(fā)人員也必須學(xué)習(xí)安全知識(shí),,才能編寫(xiě)安全的應(yīng)用。此處有關(guān)于Web應(yīng)用漏洞的重要資源: The Open Web Application Security Project (OWASP),。還有一個(gè)很好的介紹: OWASP Top Ten Vulnerability List ,。除非你理解了列表中的所有漏洞,否則不要去嘗試編寫(xiě)一個(gè)處理敏感數(shù)據(jù)的Web應(yīng)用程序,。雇主也有責(zé)任確保所有開(kāi)發(fā)人員在安全應(yīng)用開(kāi)發(fā)方面經(jīng)過(guò)充分的培訓(xùn),。

對(duì)您的應(yīng)用進(jìn)行第三方“滲透測(cè)試”是一個(gè)很好的主意。即使最好的程序員也可能會(huì)犯錯(cuò),,所以,,讓安全專(zhuān)家審計(jì)代碼尋找潛在的漏洞是有意義的。找一個(gè)值得信賴(lài)的機(jī)構(gòu)(或招聘人員)來(lái)定期審計(jì)代碼,。安全審計(jì)應(yīng)該從開(kāi)發(fā)初期就著手進(jìn)行,,并貫穿整個(gè)開(kāi)發(fā)過(guò)程。

監(jiān)控您的網(wǎng)站來(lái)發(fā)現(xiàn)入侵行為也很重要,。我建議至少雇用一名全職人員負(fù)責(zé)監(jiān)測(cè)和處理安全漏洞,。如果某個(gè)漏洞沒(méi)被發(fā)現(xiàn),攻擊者可能通過(guò)網(wǎng)站利用惡意軟件感染訪(fǎng)問(wèn)者,,因此,,檢測(cè)漏洞并及時(shí)處理是極為重要的。

常見(jiàn)疑問(wèn)
我應(yīng)該使用什么樣的哈希算法,?

可以使用:

不可使用:

  • 快速加密哈希函數(shù),如 MD5 ,、SHA1,、SHA256、SHA512,、RipeMD,、WHIRLPOOL、SHA3等,。

  • crypt()的不安全版本,。

  • 任何自己設(shè)計(jì)的加密算法。只應(yīng)該使用那些在公開(kāi)領(lǐng)域中的,、由經(jīng)驗(yàn)豐富的密碼學(xué)家完整測(cè)試過(guò)的技術(shù),。

盡管目前還沒(méi)有一種針對(duì)MD5或SHA1非常高效的攻擊手段,但它們過(guò)于古老以至于被廣泛認(rèn)為不足以用來(lái)存儲(chǔ)密碼(可能有些不恰當(dāng)),。所以我不推薦使用它們,。但是也有例外,PBKDF2中經(jīng)常使用SHA1作為它底層的哈希函數(shù),。

當(dāng)用戶(hù)忘記密碼時(shí)如何重置密碼,?

這是我個(gè)人的觀點(diǎn):當(dāng)下所有廣泛使用的密碼重置機(jī)制都是不安全的。如果你對(duì)高安全性有要求,,如加密服務(wù),,那么就不要讓用戶(hù)重設(shè)密碼。

大多數(shù)網(wǎng)站向那些忘記密碼的用戶(hù)發(fā)送電子郵件來(lái)進(jìn)行身份認(rèn)證,。要做到這一點(diǎn),,需要隨機(jī)生成一個(gè)一次性使用的令牌( token ),直接關(guān)聯(lián)到用戶(hù)的賬號(hào),。然后將這個(gè)令牌混入一個(gè)重置密碼的鏈接中,,發(fā)送到用戶(hù)的電子郵箱。當(dāng)用戶(hù)點(diǎn)擊包含有效令牌的密碼重置鏈接,,就提示他們輸入新密碼,。確保令牌只對(duì)一個(gè)賬號(hào)有效,以防攻擊者從郵箱獲取到令牌后用來(lái)重置其他用戶(hù)的密碼,。

令牌必須在15分鐘內(nèi)使用,,且一旦使用后就立即作廢,。當(dāng)用戶(hù)登錄成功時(shí)(表明還記得自己的密碼), 或者重新請(qǐng)求令牌時(shí),,使原令牌失效是一個(gè)好做法,。如果令牌永不過(guò)期,那么它就可以一直用于入侵用戶(hù)的賬號(hào),。電子郵件(SMTP)是一個(gè)純文本協(xié)議,,網(wǎng)絡(luò)上有很多惡意路由在截取郵件信息。在用戶(hù)修改密碼后,,那些包含重置密碼鏈接的郵件在很長(zhǎng)時(shí)間內(nèi)缺乏保護(hù),,因此,盡早使令牌盡快過(guò)期,,來(lái)降低用戶(hù)信息暴露給攻擊者的風(fēng)險(xiǎn),。

攻擊者能夠篡改令牌,因此不要把賬號(hào)信息和失效時(shí)間存儲(chǔ)在其中,。它們應(yīng)該以不可猜測(cè)的二進(jìn)制形式存在,,并且只用來(lái)識(shí)別數(shù)據(jù)庫(kù)中某條用戶(hù)的記錄。

千萬(wàn)不要通過(guò)電子郵件向用戶(hù)發(fā)送新密碼,。記得在用戶(hù)重置密碼時(shí)隨機(jī)生成一個(gè)新的鹽值用來(lái)加密,,不要重復(fù)使用已用于密碼哈希加密的舊鹽值。

如果賬號(hào)數(shù)據(jù)庫(kù)被泄漏或入侵,,應(yīng)該怎么做,?

你的首要任務(wù)是,確定系統(tǒng)被暴露到什么程度,,然后修復(fù)攻擊者利用的的漏洞,。如果你沒(méi)有應(yīng)對(duì)入侵的經(jīng)驗(yàn),我強(qiáng)烈建議聘請(qǐng)第三方安全公司來(lái)做這件事,。

捂住一個(gè)漏洞并期待沒(méi)人知道,,是不是很省事,又誘人,?但是這樣做只會(huì)讓你的處境變得更糟糕,,因?yàn)槟阍谟脩?hù)不知情的情況下,將它們的密碼和個(gè)人信息置于暴露風(fēng)險(xiǎn)之中,。就算你還沒(méi)有完全發(fā)生什么事情時(shí),,你也應(yīng)該盡快通知用戶(hù)。例如在首頁(yè)放置一個(gè)鏈接,,指向?qū)Υ藛?wèn)題更為詳細(xì)的說(shuō)明,;如果可能的話(huà)通過(guò)電子郵件發(fā)送通知給每個(gè)用戶(hù)告知目前的情況。

向用戶(hù)說(shuō)明他們的密碼究竟是如何被保護(hù)的:最好是使用了加鹽哈希。但是,,即使用了加鹽哈希,,惡意黑客仍然可以使用字典攻擊和暴力攻擊。如果用戶(hù)在很多服務(wù)使用相同的密碼,,惡意黑客會(huì)利用他們找到的密碼去嘗試登陸其他網(wǎng)站,。告知用戶(hù)這個(gè)風(fēng)險(xiǎn),建議他們修改所有類(lèi)似的密碼,,不論密碼用在哪個(gè)服務(wù)上,。強(qiáng)制他們下次登錄你的網(wǎng)站時(shí)更改密碼。大多數(shù)用戶(hù)會(huì)嘗試“修改”自己的密碼為原始密碼,,以便記憶,。您應(yīng)該使用當(dāng)前密碼哈希值以確保用戶(hù)無(wú)法做到這一點(diǎn),。

就算有加鹽哈希的保護(hù),,也存在攻擊者快速破解其中一些弱口令密碼的可能性。為了減少攻擊者使用這些密碼的機(jī)會(huì),,應(yīng)該對(duì)這些密碼的賬號(hào)發(fā)送認(rèn)證電子郵件,,直到用戶(hù)修改了密碼??蓞⒖记懊嫣岬降膯?wèn)題:當(dāng)用戶(hù)忘記密碼時(shí)如何重置密碼,?這其中有一些實(shí)現(xiàn)電子郵件認(rèn)證的要點(diǎn)。

另外告訴你的用戶(hù),,網(wǎng)站存儲(chǔ)了哪些個(gè)人信息,。如果您的數(shù)據(jù)庫(kù)包括信用卡號(hào)碼,您應(yīng)該通知用戶(hù)仔細(xì)檢查近期賬單并銷(xiāo)掉這張信用卡,。

應(yīng)該使用什么樣的密碼策略,?是否應(yīng)該使用強(qiáng)密碼?

如果您的服務(wù)沒(méi)有嚴(yán)格的安全要求,,那么不要對(duì)用戶(hù)進(jìn)行限制,。我建議在用戶(hù)輸入密碼時(shí),頁(yè)面顯示出密碼強(qiáng)度,,由他們自己決定需要多安全的密碼,。如果你有特殊的安全需求,那就應(yīng)該實(shí)施長(zhǎng)度至少為12個(gè)字符的密碼,,并且至少需要兩個(gè)字母,、兩個(gè)數(shù)字和兩個(gè)符號(hào)。

不要過(guò)于頻繁地強(qiáng)制你的用戶(hù)更改密碼,,最多每半年一次,,超過(guò)這個(gè)次數(shù),用戶(hù)就會(huì)感到疲勞。相反,,更好的做法是教育用戶(hù),,當(dāng)他們感覺(jué)密碼可能泄露時(shí)主動(dòng)修改,并且提示用戶(hù)不要把密碼告訴任何人,。如果這是一個(gè)商業(yè)環(huán)境,,鼓勵(lì)員工利用工作時(shí)間熟記并使用他們的密碼。

如果攻擊者入侵了數(shù)據(jù)庫(kù),,他不能直接替換哈希值登陸任意賬號(hào)么,?

是的,但如果有人入侵您的數(shù)據(jù)庫(kù),,他們很可能已經(jīng)能夠訪(fǎng)問(wèn)您的服務(wù)端上的所有內(nèi)容,,這樣他們就不需要登錄到您的賬號(hào),就可以獲得他們想要的東西,。密碼哈希(對(duì)網(wǎng)站而言)的目的不是為了保護(hù)被入侵的網(wǎng)站,,而是在入侵已經(jīng)發(fā)生時(shí)保護(hù)數(shù)據(jù)庫(kù)中的密碼。

你可以通過(guò)給數(shù)據(jù)庫(kù)連接設(shè)置兩種權(quán)限,,防止密碼哈希在遭遇注入攻擊時(shí)被篡改,。一種權(quán)限用于創(chuàng)建用戶(hù),一種權(quán)限用于用戶(hù)登陸,?!皠?chuàng)建用戶(hù)”的代碼應(yīng)該能夠讀寫(xiě)用戶(hù)表;但“用戶(hù)登陸”的代碼應(yīng)該只能夠讀取用戶(hù)表而不能寫(xiě)入,。

為什么要使用一種像HMAC的特殊算法,,而不是只將密鑰混入密碼?

如 MD5,、SHA1,、SHA2 和 Hash 函數(shù)使用 Merkle–Damg?rd ,這使得它們很容易受到所謂的長(zhǎng)度擴(kuò)展攻擊( length extension attack),。意思是給定的哈希值 H(X),,對(duì)于任意的字符串 Y,攻擊者可以計(jì)算出 H(pad(X)+Y) 的值,,而無(wú)需知道 X 的值,。其中, pad(X) 是哈希函數(shù)的填充函數(shù),。

這意味著,,攻擊者不知道密鑰的情況下,仍然可以根據(jù)給定的哈希值 H(key+message) 計(jì)算出 H(pad(key+message)+extension) ,。如果該哈希值用于身份認(rèn)證,,并依靠其中的密鑰來(lái)防止攻擊者篡改消息,,這方法已經(jīng)行不通。因?yàn)楣粽邿o(wú)需知道密鑰也能構(gòu)造出包含 message+extension 的一個(gè)有效的哈希值,。

目前尚不清楚攻擊者如何利用這種攻擊來(lái)快速破解密碼哈希,。然而,由于這種攻擊的出現(xiàn),,不建議使用普通的哈希函數(shù)對(duì)密鑰進(jìn)行哈希加密。將來(lái)也許某個(gè)高明的密碼學(xué)家有一天發(fā)現(xiàn)利用長(zhǎng)度擴(kuò)展攻擊的新思路,從而更快的破解密碼,所以還是使用 HMAC 為好,。

鹽值應(yīng)該加到密碼之前還是之后?

無(wú)所謂,,選擇一個(gè)并保持風(fēng)格一致即可,,以免出現(xiàn)互操作方面的問(wèn)題,。鹽值加到密碼之前較為普遍,。

為何本文的哈希代碼都以固定時(shí)間比較哈希值,?

使用固定的時(shí)間來(lái)比較哈希值可以防止攻擊者在在線(xiàn)系統(tǒng)使用基于時(shí)間差的攻擊,,以此獲取密碼的哈希值,,然后進(jìn)行本地破解,。

比較兩個(gè)字節(jié)序列(字符串)是否相同的標(biāo)準(zhǔn)做法是,,從第一個(gè)字節(jié)開(kāi)始,,每個(gè)字節(jié)逐一順序比較,。只要發(fā)現(xiàn)某個(gè)字節(jié)不同,,就可以知道它們是不同的,立即返回false,。如果遍歷整個(gè)字符串沒(méi)有找到不同的字節(jié),可以確認(rèn)兩個(gè)字符串就是相同的,,可以返回true,。這意味著比較兩個(gè)字符串,,如果它們相同的長(zhǎng)度不一樣,,花費(fèi)的時(shí)間不一樣。開(kāi)始部分相同的長(zhǎng)度越長(zhǎng),,花費(fèi)的時(shí)間也就越長(zhǎng),。

例如,字符串 “XYZABC” 和 “abcxyz” 的標(biāo)準(zhǔn)比較,,會(huì)立即看到,,第一個(gè)字符是不同的,,就不需要檢查字符串的其余部分,。相反,,當(dāng)字符串 “aaaaaaaaaaB” 和 “aaaaaaaaaaZ” 進(jìn)行比較時(shí),比較算法就需要遍歷最后一位前所有的 “a” ,,然后才能知道他們是不同的。

假設(shè)攻擊者試圖入侵一個(gè)在線(xiàn)系統(tǒng),這個(gè)系統(tǒng)限制了每秒只能?chē)L試一次用戶(hù)認(rèn)證,。還假設(shè)攻擊者已經(jīng)知道密碼哈希所有的參數(shù)(鹽值,、哈希函數(shù)的類(lèi)型等),除了密碼的哈希值和密碼本身。如果攻擊者能精確測(cè)量在線(xiàn)系統(tǒng)耗時(shí)多久去比較他猜測(cè)的密碼和真實(shí)密碼,那么他就能使用時(shí)序攻擊獲取密碼的哈希值,,然后進(jìn)行離線(xiàn)破解,從而繞過(guò)系統(tǒng)對(duì)認(rèn)證頻率的限制,。

首先攻擊者準(zhǔn)備256個(gè)字符串,,它們的哈希值的第一字節(jié)包含了所有可能的情況,。他將每個(gè)字符串發(fā)送給在線(xiàn)系統(tǒng)嘗試登陸,,并記錄系統(tǒng)響應(yīng)所消耗的時(shí)間,。耗時(shí)最長(zhǎng)的字符串就是第一字節(jié)相匹配的,。攻擊者知道第一字節(jié)后,并可以用同樣的方式繼續(xù)猜測(cè)第二字節(jié)、第三字節(jié)等等。一旦攻擊者獲得足夠長(zhǎng)的哈希值片段,,他就可以在自己的機(jī)器上來(lái)破解,不受在線(xiàn)系統(tǒng)的限制,。

在網(wǎng)絡(luò)上進(jìn)行這種攻擊似乎不可能。然而,,有人已經(jīng)實(shí)現(xiàn)了,,并已證明是實(shí)用的,。這就是為什么本文提到的代碼,,它利用固定時(shí)間去比較字符串,,而不管有多大的字符串,。

“慢比較( slowequals)”函數(shù)如何工作,?

前一個(gè)問(wèn)題解釋了為什么“慢比較”是必要的,,現(xiàn)在來(lái)解釋代碼如何工作。

private static boolean slowEquals(byte[] a, byte[] b)     {         int diff = a.length ^ b.length;         for(int i = 0; i < a.length="" &&="" i="">< b.length;="" i++)=""  =""  =""  =""  =""  =""  ="" diff="" |="a[i]" ^="" b[i];=""  =""  =""  =""  ="" return="" diff="=" 0;=""  =""  ="">

該代碼使用異或運(yùn)算符“^”來(lái)比較兩個(gè)整數(shù)是否相等,,而不是“==”運(yùn)算符,。下面解釋原因,。當(dāng)且僅當(dāng)兩位相等時(shí),,異或的結(jié)果將是零。這是因?yàn)椋? XOR 0 = 0,,1 XOR 1 = 0,,0 XOR 1 = 1,,1 XOR 0 = 1如果我們將其應(yīng)用到整數(shù)中每一位,當(dāng)且僅當(dāng)字節(jié)兩個(gè)整數(shù)各位都相等,,結(jié)果才是0,。

所以,在代碼的第一行中,,如果a.length等于b.length ,,相同的話(huà)得到0,否者得到非零值,。然后使用異或比較數(shù)組中各字節(jié),,并且將結(jié)果和diff求或。如果有任何一個(gè)字節(jié)不相同,,diff就會(huì)變成非零值,。因?yàn)榛蜻\(yùn)算沒(méi)有“置0”的功能,所以循環(huán)結(jié)束后diff是0的話(huà)只有一種可能,,那就是循環(huán)前兩個(gè)數(shù)組長(zhǎng)度相等(a.length == b.length),,并且數(shù)組中每一個(gè)字節(jié)都相同(每次異或的結(jié)果都非0)。

我們需要使用XOR,,而不是“==”運(yùn)算符比較整數(shù)的原因是,,“==”通常是編譯成一個(gè)分支的語(yǔ)句。例如,,C語(yǔ)言代碼中“ diff &= a == b”可能編譯以下x86匯編:

MOV EAX, [A]CMP [B], EAXJZ equalJMP doneequal:AND [VALID], 1done:AND [VALID], 0

其中的分支導(dǎo)致代碼運(yùn)行的時(shí)間不固定,,決定于兩個(gè)整數(shù)相等的程度和CPU內(nèi)部的跳轉(zhuǎn)預(yù)測(cè)機(jī)制(branch prediction),。

而C語(yǔ)言代碼“diff |= a ^ b”會(huì)被編譯為下面的樣子,它執(zhí)行的時(shí)間和兩個(gè)變量是否相等無(wú)關(guān),。

MOV EAX,,[A]XOR EAX,[B]OR [DIFF],,EAX
為何要進(jìn)行哈希,?

用戶(hù)在你的網(wǎng)站上輸入密碼,是因?yàn)樗麄兿嘈拍隳鼙WC密碼的安全,。如果你的數(shù)據(jù)庫(kù)遭到黑客攻擊,而用戶(hù)的密碼又不受保護(hù),,那么惡意黑客可以利用這些密碼嘗試登陸其他網(wǎng)站和服務(wù)(大多數(shù)用戶(hù)會(huì)在所有地方使用相同的密碼),。這不僅僅關(guān)乎你網(wǎng)站的安全,更關(guān)系到用戶(hù)的安全,。你有責(zé)任負(fù)責(zé)用戶(hù)的安全,。

今日薦文

點(diǎn)擊下方圖片即可閱讀

從Zipkin到Jaeger,Uber的分布式追蹤之道



    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶(hù)發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多