专栏首页网管叨bi叨Go Web编程--使用bcrpyt哈希用户密码

Go Web编程--使用bcrpyt哈希用户密码

上一期的文章《我们应该如何保护用户的密码》里介绍了bcrypt相较于MD5SHA-1SHA-256等哈希算法更适合用于做密码的哈希,原因就是bcrypt算法哈希字符串的速度远远慢于上面列举的那些算法。这样即使整个用户密码库被盗用后,想要通过彩虹表和暴力破解的方法猜测出用户密码的代价会非常高昂。今天的文章里就主要来看一下bcrypt哈希的组成部分以及在Go语言里如何使用bcrypt对密码字符串进行哈希。

bcrypt哈希字符串的组成

bcrypt哈希由多个部分组成。这些部分用于确定创建哈希的设置,从而可以在不需要任何其他信息的情况下对其进行验证。

上图是一个bcrypt哈希的示例图,其由四部分组成:

  • 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库三个函数的功能

// ./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程序的路由:

func RegisterRoutes(r *mux.Router) {
  ...
  indexRouter := r.PathPrefix("/index").Subrouter()
  indexRouter.HandleFunc("/password_hashing", handler.PassWordHashingHandler)
  ...
}

重启http_demo服务器后访问http://localhost:8000/index/password_hashing即可得到如下结果:

Password: secret
Hash:     $2a$14$Ael8nW7UF/En/iI7LGdyBuaIO8VREbL2CAShRN0EUQHqtmOHXh.XK
Match:    true
Cost:     14

本文分享自微信公众号 - 网管叨bi叨(kevin_tech),作者:KevinYan11

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • YAML,另一种标记语言?不止是标记语言!

    早先的文章《Kubernetes入门实践--部署运行Go项目》里我们使用YAML定义了Deployment对象,Kubernetes推荐的使用方式也是用一个YA...

    KevinYan
  • 用Golang构建gRPC服务

    继续之前,请确保你已经对gRPC概念有所了解,并且熟悉protocol buffer。需要注意的是教程中的示例使用的是 proto3版本的protocol bu...

    KevinYan
  • Laravel源码解析之Response

    之前两篇文章分别讲了Laravel的控制器和Request对象,在讲Request对象的那一节我们看了Request对象是如何被创建出来的以及它支持的方法都定义...

    KevinYan
  • ActFramework中存储与验证用户密码的机制与应用

    老码农
  • vue页面开发遇到的坑,都是泪!src属性,freemarker取值

    效果图如下 对应的连接 http://www.xinghengedu.com/getTenActivityQuestions.jspx 可以玩一玩。

    陈灬大灬海
  • CSS魔法堂:你真的理解z-index吗?

    一、前言                                 假如只是开发简单的弹窗效果,懂得通过z-index来调整元素间的层叠关系就够了。但要将...

    ^_^肥仔John
  • 基于SDN的数据中心市场将会高速增长

    BigSwitch Networks公司是软件定义网络(SDN)数据中心的主要提供商,将思科,VMware和华为等公司作为其行业竞争对手,日前推出多个组件来实现...

    SDNLAB
  • Navicat Premium v15.0.9 安装及破解

    (adsbygoogle = window.adsbygoogle || []).push({});

    乐心湖
  • JavaScript数据结构(3-1):单向链表与双向链表——单向链表篇

    在我学习这些数据结构的时候,曾经问我的同伴在生活中有没有类似的概念。我所听到的例子是购物清单和火车。但是我最终明白了,这些类比是不准确的,购物清单更类似队列,火...

    疯狂的技术宅
  • 区块链数字挖矿分红交易所系统开发

    近期,币圈大家都在讨论交易所挖矿和分红,尤其是FCoin这个平台币,随着市场的扩张是越来越火了,先有徐明星在朋友圈说其是资金盘,随时可能崩盘;后有宝二爷说极度看...

    ruiec1212

扫码关注云+社区

领取腾讯云代金券