security

用什麼樣的密碼比較安全呢

今天來講一下各大網站保存密碼的方式 如果你是engineer的話而且知道hash+salt是什麼意思可以直接跳過這篇文章 如果非CS的只是來湊湊熱鬧 那可以直接往下拉到結論 我告訴你你的密碼安不安全

Hash your password

如果你在做一個網站後端開發 一個使用者創帳號的時候 你要用一個固定的hash function在database裏存hash過後的密碼 每次使用者登入的時候 把使用者給你的密碼hash之後 看看跟你database的那個一不一樣 因為hash是不能reverse的 所以即使哪天資料外洩 hacker也無法知道你的明碼

HASH(plain_text) == saved_string

聽起來挺ok的啊

一開始的確是沒什麼問題 所以一開始網站沒有給太多密碼複雜度的限制 但隨著記憶體空間越來越便宜 hacker可以先把所有可能的hash結果存起來 再一一比對他從database拿到的hashed_value跟他先算好的表有沒有match match到你的密碼就被破解

光說不練假把戲 來點數學吧 十年前安全性沒人要求的時候 一般人的密碼都挺短的而且都是英文+數字 假設長度是7的話 那所有的可能明碼也才(26+10)^7種 假設現在是用md5 hash(hash完的長度是128bits)

(1*7 + 128 / 8)*(26+10)^7 bytes = 1.8TB

意思是我存下所有的mapping 1*7是明碼 128/8是hash過的密碼byte大小

在2017年這個容量簡直輕鬆愉快啊 那麼該怎麼辦呢

Salt

這個時候就需要加點隨機的東西增加亂度了 解法就是在每個人創帳號密碼的時候 隨機生成一個字串 加在明碼後面或是穿插明碼其中 Verify的時候也一樣 只要server記得每個人的隨機字串就可以

HASH(plain_text + salt) == saved_string

最好連salt的長度也是random(當然要越長越好) 這樣的話hacker就必須所有的長度都有個表 那其實更快的方式是直接把username或是email加進來hash 基本上就是增加原本字串的難度 畢竟所有md5的output是2^128 沒有一個machine可以記得了所有的input 而增加難度最簡單的方式 就是增加長度 長度每加一 難度變36倍

另一種就是增加可能的字母 加上大寫(26)加上特殊符號(32)(Password special character)底數直接從36 -> 94 那自然就更難了

所以為什麼大網站都會要求你用長度最少12 最少要有一個大寫 一個小寫 一個特殊字母 一個數字 這樣如果hacker萬一哪天破解了這個網站的database拿到了hash過的密碼 大概未來一兩年內都還不會有事 但如果再加上random長度的salt 基本上就不太可能用這種暴力法破解

問題

Q:既然salt是存在database的明碼 那遲早有一天記憶體大到可以cover長度10的密碼 那再把它減去salt不就得到user的密碼了嗎

A:所以salt有兩個目的 第一個是讓hash前的字串總長度拉長 這樣即使使用者給的長度不夠 還是可以增加暴力破解難度

舉個例子 如果user密碼長度是10 salt長度是5 那總長度是15的密碼就不太可能用建表暴力解再減salt的方式

Q:總長度15的不好建 10的總可以了吧 他不就可以把所有排列組合+salt建表嗎

A:答對了!這就是為什麼salt要random

salt的第二個目的是可以把損失降到最低 那個hacker一次還是只能破解一個人的密碼 因為他必須對每個新的salt 重新建表 這樣可以幫security部門爭取時間叫人家改密碼

如果我是hacker

當然不是說什麼順便hack生日這種資訊 排列組合猜一猜 這是要猜到什麼時候 這個blog怎麼可能講出這麼沒格調的話 基本概念很簡單 因為大家懶 十年前大家需要辦帳號時都有過密碼 而當時對於密碼的要求不高 所以很有可能大多數的密碼都只有小寫英文(因為大腦不喜歡英文單字中參雜數字這種不協調感) 然後呢 之後安全意識抬頭 大家要求要有大寫字母和特殊字元 可是大家又不想改原本的密碼太多 所以就很簡單的加在原本的密碼後面 考慮這些歷史因素的話 我就會先創建所有的可能密碼的hash 大概長這樣

abcdefgH0!(前七~九個是小寫英文 後面一個大寫英文 後面一個數字 後面一個特殊符號)

我相信這樣應該會中一些XD 但如果網站有加salt那就什麼都不管用了 這就是為什麼你身為develoer要加salt的原因 就像短版效應一樣

你密碼的安全度取決於所有你用同一個密碼的網站裡 security做最差的網站的安全度

講這麼多 所以我的密碼到底夠不夠強呢

大概念就是越長越好 這是最重要的因素 其中穿插大小寫互換跟數字 然後特殊符號穿插其中(不要擺最前也不要擺最後) 雖然很麻煩 但打一下就習慣

所以你的密碼到底有多安全呢 長度10都是英文小寫跟長度8但可以有特殊符號 哪個比較安全呢

簡單的計算方式就是

(1*n + 128 / 8)*(26 or 36 or 62 or 94)^n

n是密碼長度

26就是只有小寫英文

36就是只有小寫英文+數字

62就是只有大小寫英文+數字

94就是只有大小寫英文+數字+特殊符號

我的經驗法則是如果你的數字小於10^24 那大概就跟jon snow一樣

Alt text

建議你換個密碼囉!