今時今日要儲底Password做認証,點先至夠?
唔用plaintext兼用hash,只係答啱咗一半
咁啱有知名學會¹嘅會員資料俾人hack咗,DB dump哂出來,發現會員資料裡面嘅密碼都係以明文(plaintext)儲存…
然而,好多網民留言話save底password應該用hash用sha256用salt啦,呢類答案其實又只係啱咗一半都冇,情況令人擔心。
Hash嘅問題
Hashing雖然係one-way,但hashing algorithm嘅首要設計目的係對資料做校驗,所以算法追求越快越好,同password驗証想bruteforce慢啲嘅目的係背道而馳。
所以用以下嘅alogrithm去儲底password嘅話:
password_hash = sha256(password + salt)
係好少少,但同plaintext唔會差好遠。
同樣地,HMAC(即使以SHA-256做底)都係一樣唔太好。
好嘅做法
簡單來講
- 用專用嘅alogrithm或者API,唔好自己reinvent the wheel,例如:Argon2, bcrypt。PHP例如用
password_hash
噉。 - 呢啲算法都要指定一個rounding參數,對自己嘅執行環境做個benchmark、配合預估嘅流量,調校一個自己接受之餘又最慢(最多round)嘅設定。
- 除咗算法加咗鹽(salt)之外,進一步落埋胡椒(pepper) — 即係喺所有plaintext再加一個application-wide嘅long random salt,噉樣即使DB被dump但app執行環境無被打破嘅話,壞人都好難bruteforce到任何嘢。
點解唔用hashing嘅算法?
上面講到,hashing滿足到one-way但係太過快,所以就有專做password hashing嘅algorithm。佢哋例如會要求做好多memory操作,導致即使用GPU都好難行得快,因為個樽頸位會去咗memory bandwidth度。
乜嘢係round?
RAM、CPU都會越來越快,但可以通過同一條算法擴大複雜度而使要更多時間先可以攻破。增加複雜度嘅方法唔一定係單純地loop多幾個round,但呢個難度參數大家都習慣咗係叫round — 所以唔好自己傻傻哋自己for-loop去做。
乜嘢係salt?
為咗對付彩虹表(rainbow table) — 即係預先計定哂絕大部分密碼對應嘅hash結果,所有呢類算法都會加一個隨機資料串先至令去做hashing。salt會以明文方式記錄喺hashing結果入面,噉樣做認証時re-hash就可以用返同一個salt。
由於每一筆紀錄用嘅salt都係隨機,就冇辦法用單一rainbow table去一口氣破哂佢哋。
噉pepper又係乜呢?
西餐通常係salt + pepper,廣東口味嘅話可能係加鹽加醋嘅🤣(?
anyway,pepper呢度係指可以再隨機生成一個passphrase字符串,喺做hashing前都加上去,但pepper就唔似salt噉放喺結果入面、即唔會save落DB,而只係放喺application嘅runtime config。
萬一DB被破,資料倒哂出來,但application server本身無事嘅話,基本上就brute force唔到出來。
更好嘅做法 — 直接唔好用password啦
Password又易唔記得、又可能會被bruteforce、或俾壞人social engineering或phishing釣魚套料,直接用passwordless其實都係個辦法。冇咗password就唔會有上述嘅問題。
- 每次login都直接send email用驗証碼或撳link — 即係Magic Links
- 引入PassKey(即WebAuthn),靠OS綁埋hardware device做authentication — Windows, Mac, Linux, iOS, Android都有support
- 用social login,即係用Google、Facebook等login用oauth2接入、又或用auth0之類嘅federated identity就唔使自己搞。
註
[1]: 呢個「學會」係出咗名炎上🤡