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

相关文章
相关标签/搜索