上一期的文章《咱們應該如何保護用戶的密碼》裏咱們介紹了bcrypt
相較於MD5
,SHA-1
...SHA-256
等哈希算法更適合用於作密碼的哈希,緣由就是bcrypt
算法哈希字符串的速度遠遠慢於上面列舉的那些算法。這樣即便整個用戶密碼庫被用戶盜用後想要經過彩虹表和暴力破解的方法猜想出用戶的密碼代價會很是高昂。今天的文章裏就主要來看一下bcrypt
哈希的組成部分以及在Go
語言裏如何使用bcrypt
對密碼字符串進行哈希。golang
bcrypt
哈希由多個部分組成。這些部分用於肯定建立哈希的設置,從而能夠在不須要任何其餘信息的狀況下對其進行驗證。算法
上圖是一個bcrypt
哈希的示例圖,其由四部分組成:shell
Prefix
說明了使用的bcrypt
的版本Cost
是進行哈希的次數-數字越大生成bcrypt
的速度越慢,成本越大。一樣也意味着若是密碼庫被盜,攻擊者想經過暴力破解的方法猜想出用戶密碼的成本變得越昂貴。Salt
是添加到要進行哈希的字符串中的隨機字符(21.25個字符),因此使用bcrypt
時不須要咱們在表裏單獨存儲Salt
。Hashed Text
是明文字符串最終被bcrypt
應用這些設置哈希後的哈希文本。另外不管什麼方法:每一個密碼加單獨的鹽進行哈希,使用bcrypt
進行哈希等等,若是用戶使用很是簡單的密碼例如password
或123456
,仍是能被猜想出來的,因此在用戶設置密碼時應該禁止他們輸入簡單的密碼。編程
bcrypt
的原理和實現都很是複雜,不過經常使用的編程語言都有實現bcrypt
的包讓咱們直接使用,在Go
語言裏是經過golang.org/x/crypto/bcrypt
包提供bcrypt
相關功能給開發者使用的。服務器
接下來咱們在http_demo
項目裏演示一下使用bcrypt
作密碼哈希和驗證的方法,首先咱們須要安裝一下bcrypt
包編程語言
$ go get golang.org/x/crypto/bcrypt
bcrypt
包只提供了三個函數:函數
CompareHashAndPassword
用於比對bcrypt
哈希字符串和提供的密碼明文文本是否匹配。GenerateFromPassword
以給定的Cost
返回密碼的bcrypt
哈希。若是給定的成本小於MinCost
,則將成本設置爲DefaultCost
(10)。Cost
返回用於建立給定bcrypt
哈希的哈希成本。未來密碼系統爲了應對更大的計算能力而增長哈希成本時,該功能能夠用於肯定哪些密碼須要更新。咱們建立一個處理請求的Handler
程序,演示bcrypt
庫三個函數的功能spa
// ./handler/password_hashing.go package handler import ( "fmt" "golang.org/x/crypto/bcrypt" "net/http" ) func HashPassword(password string) (string, error) { bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14) return string(bytes), err } func CheckPasswordHash(password, hash string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) return err == nil } func GetHashingCost(hashedPassword []byte) int { cost, _ := bcrypt.Cost(hashedPassword) // 爲了簡單忽略錯誤處理 return cost } func PassWordHashingHandler(w http.ResponseWriter, r *http.Request) { password := "secret" hash, _ := HashPassword(password) // 爲了簡單忽略錯誤處理 fmt.Fprintln(w,"Password:", password) fmt.Fprintln(w, "Hash: ", hash) match := CheckPasswordHash(password, hash) fmt.Fprintln(w,"Match: ", match) cost := GetHashingCost([]byte(hash)) fmt.Fprintln(w,"Cost: ", cost) }
增長Handler
程序的路由:code
func RegisterRoutes(r *mux.Router) { ... indexRouter := r.PathPrefix("/index").Subrouter() indexRouter.HandleFunc("/password_hashing", handler.PassWordHashingHandler) ... }
重啓http_demo
服務器後訪問http://localhost:8000/index/password_hashing
便可獲得以下結果:router
Password: secret Hash: $2a$14$Ael8nW7UF/En/iI7LGdyBuaIO8VREbL2CAShRN0EUQHqtmOHXh.XK Match: true Cost: 14
本文源代碼已經打包上傳,公衆號回覆gohttp13
便可得到下載連接。若是以爲個人文章有收穫,請幫忙點"在看"分享給更多人。