Go Web編程--使用bcrpyt哈希用戶密碼

上一期的文章《咱們應該如何保護用戶的密碼》裏咱們介紹了bcrypt相較於MD5SHA-1...SHA-256等哈希算法更適合用於作密碼的哈希,緣由就是bcrypt算法哈希字符串的速度遠遠慢於上面列舉的那些算法。這樣即便整個用戶密碼庫被用戶盜用後想要經過彩虹表和暴力破解的方法猜想出用戶的密碼代價會很是高昂。今天的文章裏就主要來看一下bcrypt哈希的組成部分以及在Go語言裏如何使用bcrypt對密碼字符串進行哈希。golang

bcrypt哈希字符串的組成

bcrypt哈希由多個部分組成。這些部分用於肯定建立哈希的設置,從而能夠在不須要任何其餘信息的狀況下對其進行驗證。算法

上圖是一個bcrypt哈希的示例圖,其由四部分組成:shell

  • Prefix說明了使用的bcrypt的版本
  • Cost是進行哈希的次數-數字越大生成bcrypt的速度越慢,成本越大。一樣也意味着若是密碼庫被盜,攻擊者想經過暴力破解的方法猜想出用戶密碼的成本變得越昂貴。
  • Salt是添加到要進行哈希的字符串中的隨機字符(21.25個字符),因此使用bcrypt時不須要咱們在表裏單獨存儲Salt
  • Hashed Text是明文字符串最終被bcrypt應用這些設置哈希後的哈希文本。

另外不管什麼方法:每一個密碼加單獨的鹽進行哈希,使用bcrypt進行哈希等等,若是用戶使用很是簡單的密碼例如password123456,仍是能被猜想出來的,因此在用戶設置密碼時應該禁止他們輸入簡單的密碼。編程

Go語言使用bcrypt

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便可得到下載連接。若是以爲個人文章有收穫,請幫忙點"在看"分享給更多人。

第1頁.png

相關文章
相關標籤/搜索