Golang每日一库之bcrypt

科技资讯 投稿 22100 0 评论

Golang每日一库之bcrypt

官方文档: https://pkg.go.dev/golang.org/x/crypto/bcrypt

前言

然后今天就来说说密码学,我们在做鉴权 做用户处理时 会把密码存储到数据库中,但是这个密码我们肯定不能明文去存储,如果这个数据库链接一旦被别人拿到
那后果是不堪设想的。不仅仅是为了防止系统管理员或者DBA等公司人员获得用户的密码,也是防止被黑客拖库产生更大的信息泄露。
如果黑客通过不法手段获取了服务的数据库存储信息,盗取里面的内容,从而直接获得明文密码,那么影响就会很大。
所以我们的密码一般通过几种方式去加密存储

    其实个人觉得MD5加密不太好,因为MD5是不加盐的,虽然是不可逆的,但是黑客其实会针对常见的一些密码,生成彩虹表。
    彩虹表是什么呢?
    是用于加密散列函数逆运算的预先计算好的表,常用于破解加密过的密码散列(维基百科)
    所以相对的感觉安全等级不是很够。

  1. SHA-1基于MD5,MD5又基于MD4
    SHA-1是由美国标准技术局(NIST)颁布的国家标准,是一种应用最为广泛的Hash函数算法,也是目前最先进的加密技术,被政府部门和私营业主用来处理敏感的信息。
    这个缺点个人认为和 MD5一样。

  2. 我之前也写过相应的文章[https://www.cnblogs.com/zichliang/p/16653303.html] 里面有相应的hmasha加密
    HMAC是密钥相关的哈希运算消息认证码(Hash-basedMessageAuthenticationCode),HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。
    HMAC是需要一个密钥的。所以,HMACSHA1也是需要一个密钥的,而SHA1不需要。

  3. CRC的全称为CyclicRedundancyCheck,中文名称为循环冗余校验。它是一类重要的线性分组码,编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。实际上,除数据通信外,CRC在其它很多领域也是大有用武之地的。例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“BadCRC”错误,由此它在数据存储方面的应用可略见一斑。

本文介绍一种加密方式 bcrypt

概述

由bcrypt加密的文件可在所有支持的操作系统和处理器上进行转移。它的口令必须是8至56个字符,并将在内部被转化为448位的密钥。然而,所提供的所有字符都具有十分重要的意义。密码越强大,数据就越安全。

具体来说,bcrypt使用美国密码学家保罗·柯切尔的算法实现。随bcrypt一起发布的源代码对原始版本作了略微改动。

以上内容来自于wiki维基百科 >>>> https://zh.wikipedia.org/wiki/Bcrypt

bcrypt基本介绍

bcrypt就是一种加盐的单向Hash,不可逆的加密算法,同一种明文(plaintext),每次加密后的密文都不一样,而且不可反向破解生成明文,破解难度很大
而我们熟知的另一种不可逆的加密算法
md5 是不加盐的单向Hash,不可逆的加密算法,同一个密码经过hash的时候生成的是同一个hash值,在大多数的情况下,有些经过md5加密的方法将会被破解。

总的来说,BCrypt比MD5更安全,但加密更慢。
各有优缺点吧。

https://www.bejson.com/encrypt/bcrpyt_encode/

安装

go get -u golang.org/x/crypto/bcrypt

cost常量分类

const (
	MinCost     int = 4  // 传递给GenerateFromPassword的最小允许开销
	MaxCost     int = 31 // 传递给GenerateFromPassword的最大允许开销
	DefaultCost int = 10 // 如果将低于MinCost的cost传递给GenerateFromPassword,则实际设置的cost

使用

这里我们直接看官方写好的测试用例,可能需要 ...(你懂的
https://cs.opensource.google/go/x/crypto/+/refs/tags/v0.8.0:bcrypt/bcrypt_test.go

GenerateFromPassword 生成一个hash密码

GenerateFromPassword不接受长度超过72字节的密码,这是bcrypt操作的最长密码

password, _ := bcrypt.GenerateFromPassword([]byte("123", bcrypt.DefaultCost
fmt.Println(string(password

结果如下
第一次

第二次
$2a\(10\Np1EBVQ9DZXMvIUkT7Y2P.cA0psEmW2SAVJYcCDqDDN8TsASo7aZm

注: 每次结果都不一样 因为这不是MD5加密,会通过加盐来完成不可逆的加密

Cost方法 返回给定的cost

简单来说 返回上文的 bcrypt.DefaultCost

cost, _ := bcrypt.Cost([]byte("$2a$10$XgLBtSfJsrBd.liLOYWddOYWYWboBUAlKmivcSwq647C3vTNUOVMO"
fmt.Println(cost

结果如下

CompareHashAndPassword 对比明文密码和散列密码

CompareHashAndPassword,将返回的散列密码与其明文版本进行比较。

password, _ := bcrypt.GenerateFromPassword([]byte("123", bcrypt.DefaultCost
fmt.Println(string(password

// 可以解析出上文
cost, _ := bcrypt.Cost([]byte("$2a$10$XgLBtSfJsrBd.liLOYWddOYWYWboBUAlKmivcSwq647C3vTNUOVMO"
fmt.Println(cost

err := bcrypt.CompareHashAndPassword(password, []byte("123"
if err != nil {
	fmt.Println("密码验证错误", err
}
fmt.Println("密码验证成功>>>", nil

结果

10
密码验证成功>>>

bcrypt某些错误类型

    type HashVersionTooNewError byte

func (hv HashVersionTooNewError Error( string 调用error返回字符串

    type InvalidCostError int

func (ic InvalidCostError Error( string 调用error返回字符串

    type InvalidHashPrefixError byte

当哈希以“$”以外的内容开头时,从 CompareHashAndPassword 返回的错误
func (ih InvalidHashPrefixError Error( string 调用error返回字符串

本文

编程笔记 » Golang每日一库之bcrypt

赞同 (107) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽