组队大项目--密码加密篇 brcypt | 青训营笔记

89 阅读2分钟

这是我参与「第五届青训营 」笔记创作活动的第4天

维基百科介绍

bcrypt是由Niels Provos和David Mazières设计的密码散列函数,基于Blowfish密码,于1999年在USENIX上发表。除了加入盐来防止彩虹表攻击,bcrypt是一个自适应函数:随着时间的推移,迭代次数可以增加,使其更慢,所以即使计算能力增加,它仍然可以抵抗暴力搜索攻击。

bcrypt函数是OpenBSD的默认密码哈希算法,也是一些Linux发行版(如SUSE Linux)的默认算法。

bcrypt在C, C++, C#, Embarcadero Delphi, Elixir, Go, Java, JavaScript,Perl, PHP, Python, Ruby, 和其他语言中都有实现。

Blowfish在区块密码中因其昂贵的密钥设置阶段而引人注目。它从子密钥的标准状态开始,然后用这个状态对部分密钥进行区块加密,并使用该加密的结果(在散列方面更精确)来替换一些子密钥。然后,它使用这个修改过的状态来加密另一部分的密钥,并使用结果来替换更多的子密钥。它以这种方式进行,使用逐步修改的状态来散列钥匙和替换状态的位数,直到所有的子钥匙都被设置。

Provos和Mazières利用了这一点,并进一步发展了它。他们为Blowfish开发了一种新的密钥设置算法,并将其命名为 "Eksblowfish"("昂贵的密钥计划Blowfish")。密钥设置从标准Blowfish密钥设置的修改形式开始,其中盐和密码都被用来设置所有的子密钥。然后进行若干轮,应用标准Blowfish密钥算法,交替使用盐和密码作为密钥,每一轮都从上一轮的子密钥状态开始。理论上,这并不比标准的Blowfish密钥计划更强大,但重新键入的轮数是可配置的;因此,这个过程可以变得任意缓慢,这有助于阻止对哈希或盐的暴力攻击。

Golang中使用方法

在golang包为"golang.org/x/crypto/bcrypt"

使用范例如下


package utils

import "golang.org/x/crypto/bcrypt"

// 密码加密: pwdHash 
func PasswordHash(pwd string) (string, error) {
	bytes, err := bcrypt.GenerateFrompwd([]byte(pwd), bcrypt.DefaultCost)
	if err != nil {
		return "", err
	}

	return string(bytes), err
}

// 密码验证: pwdVerify
func PasswordVerify(pwd, hash string) bool {
	err := bcrypt.CompareHashAndpwd([]byte(hash), []byte(pwd))

	return err == nil
}

调用方法如下

package main

import (
	"fmt"
	"password_demo/utils"
)

func checkLogin(loginPwd string, hash string) bool {
	return utils.PasswordVerify(loginPwd, hash)
}

func main() {

	fmt.Println("=> hi password!")

	// loginPwd := "123456"
	loginPwd := "admin"
	dbPwd := "$2a$10$ND3xmjbf27oBfjh9AcHxxuLViQubQzVwR/DEYcfjB9RwwR.8h8j6W"

	if checkLogin(loginPwd, dbPwd) {
		fmt.Println("=> 密码输入正确!")
	} else {
		fmt.Println("=> failed 密码错误,请重新输入!")
	}
}