天天看點

mosquitto鑒權插件mosquitto-auth-plug的加密算法mosquitto-auth-plug

mosquitto-auth-plug

PBKDF2加密

PBKDF2其實就是選擇一種雜湊演算法,把密碼加鹽後經過多次疊代計算進行加密。當然肯定是不可逆的,可以防止碰撞破解,疊代次數越多越安全。

mosquitto-auth-plug使用了PBKDF2加密,編譯後得到的np可執行程式可以進行加密:(下面假設密碼為admin)

./np -p admin

得到加密密碼:
PBKDF2$sha256$901$qiCmZmc2ZKEJkEaL$7Nw6lpv9G0IoEgxcTfEbx4ajtMQD3shC
           

傳回的密碼使用$符号分隔,最前為PBKDF2辨別,預設使用sha256雜湊演算法,進行了901次疊代加密,然後是使用openssl生成随機數經過BASE64的字元串也就是鹽,最後是真正PBKDF2生成的Key。

把這個密碼存儲到資料庫以後,當使用者使用使用者名和密碼登入上來時,auth-plug會根據使用者名查詢資料庫得到密碼,然後根據$分割辨別的定義來進行加密密碼,最後把加密後的密碼跟資料庫的密碼進行對比就知道使用者的密碼是否正确。

使用golang計算auth-plug的密碼

golang.org/x/crypto/pbkdf2

這個就是go的PBKDF2加密算法,golang.org被牆上不去,不過沒關系,在github上有crypto的鏡像:https://github.com/golang/crypto

PBKDF2調用方法:

通過檢視auto-plug的np.c源碼檔案,可以知道是怎麼生成密碼的,其實就是先生成鹽,調用openssl的RAND_bytes函數生成預設12位元組随機數然後進行base64生成鹽。

iter預設為901次,keyLen的長度為24,h雜湊演算法為sha256,調用Key方法後将傳回的[]byte數組經過base64.StdEncoding.EncodeToString得到加密Key,最終按照上面寫的規則使用$符号拼接得到最終的密碼。

加密速度和密碼長度優化

測試了一下使用預設iter = 901的golang版本加密,感覺速度太慢了,按這速度一台伺服器想高并發根本不可能,反正一般系統的安全性并不要這麼高,那麼可以調節減少iter次數,其實就算iter設為零,PBKDF2也執行了兩次sha256,加上16位元組長度的salt,比一般網站的MD5安全多了,先湊合着用吧。

其實我想測試一下np.c的加密速度比golang的會快多少,如果差距大的話可以使用cgo寫個替代,暫時還沒空搞。

十幾分鐘後,還是忍不住修改了np.c程式簡單測試了一下,同樣iter=901,c版本比golang幾乎快了一倍,汗!

不過當iter比較小比如iter=9時,兩者差距不大。甚至當iter=0時,go版本更快一點,應該是c版本沒有優化每次調用都重新配置設定記憶體,而go勝在有GC。

對于我的應用來說,因為采用較小的iter是以沒必要用cgo優化了。

golang自帶的crypto/rand太慢,使用了

github.com/NebulousLabs/fastrand

會快很多,生成12位元組的随機串快一倍,如果生成的位元組數大的話會更快,甚至快10倍以上。

另外最終用$拼接的密碼長度也太長了,如果資料庫用的是Redis的話太浪費記憶體,前面的3段可以大大縮短,甚至都不用,然後修改mosquitto-auth-plug的源碼來配合優化減少長度。

如果不怕慢而是希望提高安全性,那麼把iter設的更大值即可。

當然既然有源碼,那麼使用什麼加密方法自己都可以随便改,如果要求高甚至可以改為安全性更高的bcrypt。

魚和熊掌不可兼得,越安全的哈希加密肯定是速度越慢,因為暴力破解者也需要更多的時間來碰撞破解,安全性就是提高破解者的成本讓其得不償失。

繼續閱讀