密碼加鹽哈希的一個(gè)實(shí)踐

安全第一

背景

開發(fā)web應(yīng)用,很多時(shí)候會(huì)設(shè)計(jì)一個(gè)用戶系統(tǒng)。一旦涉及到用戶的隱私信息关霸,作為開發(fā)者必須慎重對(duì)待。經(jīng)常在網(wǎng)上能看到類似這樣的新聞:2011年中國網(wǎng)站用戶信息泄露事件杰扫。一旦發(fā)生這樣的事情队寇,總是會(huì)引起用戶的恐慌,所以章姓,用戶密碼的保護(hù)是這其中的重中之重备籽。

在工作過程中我也遇到了一些類似的問題嗡髓,在這里簡(jiǎn)單記錄自己的思考。主要的實(shí)踐語言是python,其他的語言道理相通坛悉。驗(yàn)證方式是最常見的user-password口令驗(yàn)證

存儲(chǔ)密碼

作為例子,使用mysql映跟,設(shè)計(jì)一個(gè)最簡(jiǎn)單的用戶表迹卢。

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `login_name` varchar(32) NOT NULL,
  `encrypted_password` varchar(128) NOT NULL,
  `create_time` bigint(20) NOT NULL,
  `modify_time` bigint(20) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `login_name` (`login_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

login_name用于存儲(chǔ)用戶名,encrypted_password對(duì)應(yīng)加密后的密文银还。

加密方式

很明顯用戶的密碼不能明文存儲(chǔ)风宁。一旦數(shù)據(jù)庫被攻破,一切都完了见剩。

考慮到用戶注冊(cè)/登陸的場(chǎng)景杀糯。一個(gè)新用戶注冊(cè)進(jìn)來一般的流程如下:

  1. 用戶新建一個(gè)賬號(hào),輸入賬號(hào)和密碼苍苞,相關(guān)數(shù)據(jù)傳送到服務(wù)器固翰。
  2. 服務(wù)端接收賬號(hào)和密碼(明文),將用戶名加密后的明文存入數(shù)據(jù)庫羹呵。
  3. 用戶登陸時(shí)輸入賬號(hào)名和密碼骂际,上傳至服務(wù)端。
  4. 服務(wù)端用賬號(hào)和加密后的明文與數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行比對(duì)冈欢,如果相同則通過驗(yàn)證歉铝。
  5. 下次登陸重復(fù)過程3,4

在第4步的時(shí)候凑耻,如果無法匹配太示,不能提示用戶“密碼出現(xiàn)錯(cuò)誤”,或者“用戶名不存在”這樣的錯(cuò)誤香浩,這樣會(huì)讓攻擊者在破解的時(shí)候排除一些錯(cuò)誤選項(xiàng)类缤。而應(yīng)該提示“用戶名或密碼出現(xiàn)錯(cuò)誤”。

加密的算法實(shí)現(xiàn)比較成熟的有SHA256, SHA512, RipeMD, WHIRLPOOL邻吭,在選擇加密方式的時(shí)候直接用就行餐弱。

可能存在的風(fēng)險(xiǎn)

假設(shè)一個(gè)場(chǎng)景,數(shù)據(jù)庫被攻破了,黑客拿到了數(shù)據(jù)庫中的密文膏蚓,他/她如何通過這個(gè)密文得到用戶的密碼呢瓢谢?

  1. 字典攻擊和暴力破解
    最簡(jiǎn)單的攻擊方式就是猜一個(gè)密碼,用這個(gè)密碼計(jì)算一個(gè)hash值驮瞧,然后和密文進(jìn)行比對(duì)氓扛。如果值一樣,就說明這個(gè)密碼是正確的剧董。這個(gè)最常用的辦法就是字典攻擊暴力破解幢尚。

  2. 彩虹表

應(yīng)對(duì)的技術(shù)

加鹽

實(shí)踐

前面廢話那么多,這里直接上代碼翅楼,再進(jìn)行說明尉剩。

import hashlib
import binascii
import base64
import os

dk_len = 24
salt_len = 24
password_encrypt_version = 'v1'
iterations = 1000

def pbkdf2(salt, password):
    dk = hashlib.pbkdf2_hmac(hashlib.sha1().name, password.encode('utf8'), base64.b16decode(salt.upper()), iterations, dk_len)
    return binascii.hexlify(dk)

def encrypt_pass(password):
    salt = binascii.hexlify(os.urandom(salt_len))
    encrypted_pass = pbkdf2(salt, password)
    return '%s:%d:%s:%s' % (password_encrypt_version, iterations, salt, encrypted_pass)

不要使用自己定義的hash函數(shù)

加密方法已經(jīng)有了對(duì)應(yīng)的工業(yè)實(shí)現(xiàn)。自己造輪子在大多數(shù)時(shí)候都會(huì)引入風(fēng)險(xiǎn)毅臊,特別是涉及到敏感信息理茎,這種風(fēng)險(xiǎn)是非常大的。

使用慢hash算法

密碼的安全是由密碼的生命周期和破解周期決定管嬉,使用慢HASH算法皂林,目的是降低破解的速度。這里使用的是pbkdf2算法蚯撩,python中有對(duì)應(yīng)的函數(shù)础倍。
函數(shù)原型

hashlib.pbkdf2_hmac(name, password, salt, rounds, dklen=None)

rounds決定了算法的快慢。這個(gè)值要綜合多方面的考慮胎挎。太小沟启,破解難度降低;太大犹菇,消耗計(jì)算德迹,造成用戶登陸時(shí)等待驗(yàn)證時(shí)間過長(zhǎng),會(huì)降低用戶體驗(yàn)揭芍。這里折衷取1000胳搞。
dklen設(shè)置hash結(jié)果的長(zhǎng)度,這里設(shè)置為24称杨。

加鹽

  • 使用偽隨機(jī)數(shù)產(chǎn)生器(CSPRNG)生成鹽值肌毅,這樣更加安全。具體到python姑原,應(yīng)該使用os.urandom這個(gè)方法悬而。
  • 不要重復(fù)使用一個(gè)鹽值。每次都應(yīng)該聲稱一個(gè)新的鹽值页衙。
  • 鹽值不能取得太短摊滔,過短的鹽值會(huì)降低安全性,這里取24店乐。

鹽值和密文一起存儲(chǔ)

最后密文的形式是

version:rounds:salt:hash_result

不要多次進(jìn)行hash

這毫無意義

驗(yàn)證

在認(rèn)證的時(shí)候艰躺,根據(jù)傳入的用戶名取出存儲(chǔ)的密文,從密文中取出rounds眨八,salt
對(duì)明文再次進(jìn)行計(jì)算腺兴,結(jié)果與存儲(chǔ)的hash結(jié)果進(jìn)行比對(duì),相同即通過驗(yàn)證廉侧。

其他的一些問題

針對(duì)用戶在登陸的時(shí)候页响,明文可能在網(wǎng)絡(luò)傳輸?shù)臅r(shí)候被監(jiān)聽到,可以在http通信時(shí)采用ssl加密的做法段誊。
或者采用其他身份驗(yàn)證方法闰蚕。

參考資料

在進(jìn)行實(shí)踐的時(shí)候參考了這篇文章,這篇文章深入淺出地講解了安全加密连舍,非常值得一讀没陡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市索赏,隨后出現(xiàn)的幾起案子盼玄,更是在濱河造成了極大的恐慌,老刑警劉巖潜腻,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件埃儿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡融涣,警方通過查閱死者的電腦和手機(jī)童番,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暴心,“玉大人妓盲,你說我怎么就攤上這事∽ㄆ眨” “怎么了悯衬?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)檀夹。 經(jīng)常有香客問我筋粗,道長(zhǎng),這世上最難降的妖魔是什么炸渡? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任娜亿,我火速辦了婚禮,結(jié)果婚禮上蚌堵,老公的妹妹穿的比我還像新娘买决。我一直安慰自己沛婴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布督赤。 她就那樣靜靜地躺著嘁灯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪躲舌。 梳的紋絲不亂的頭發(fā)上丑婿,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音没卸,去河邊找鬼羹奉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛约计,可吹牛的內(nèi)容都是我干的诀拭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼煤蚌,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼炫加!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起铺然,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤俗孝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后魄健,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赋铝,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年沽瘦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了革骨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡析恋,死狀恐怖良哲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情助隧,我是刑警寧澤筑凫,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站并村,受9級(jí)特大地震影響巍实,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哩牍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一棚潦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧膝昆,春花似錦丸边、人聲如沸叠必。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挠唆。三九已至,卻和暖如春嘱吗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背滔驾。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國打工谒麦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人哆致。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓绕德,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親摊阀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子耻蛇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容