实例:密码加密

1.介绍

韭菜本来是php程序猿一枚,以前写laravel的时候,感觉laravel中的密码加密很神奇,相同的密码,加密出来的结果不一样,但是密码比对的时候确实一样的,非常好奇,然后研究了一番laravel的密码加密方式,发现采用的加密方式是bcrypt,于是去google了一波。

bcrypt是单向Hash加密算法,类似Pbkdf2算法 不可反向破解生成明文。

2.Bcrypt是怎么加密的?

bcrypt有四个变量:

  1. saltRounds: 正数,代表hash杂凑次数,数值越高越安全,默认10次。
  2. myPassword: 明文密码字符串。
  3. salt: 盐,一个128bits随机字符串,22字符
  4. myHash: 经过明文密码password和盐salt进行hash,个人的理解是默认10次下 ,循环加盐hash10次,得到myHash

每次明文字符串myPassword过来,就通过10次循环加盐salt加密后得到myHash, 然后拼接BCrypt版本号+salt盐+myHash等到最终的bcrypt密码 ,存入数据库中。 这样同一个密码,每次登录都可以根据自省业务需要生成不同的myHash, myHash中包含了版本和salt,存入数据库。

即使黑客得到了bcrypt密码,他也无法转换明文,因为之前说了bcrypt是单向hash算法

3.如何验证密码的?

bcrypt校验时,从myHash中取出salt,salt跟password进行hash;得到的结果跟保存在DB中的hash进行比对。

4.使用go实现bcrypt加密密码

pkg/hash/bcrypt.go

package hash

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

type Bcrypt struct {
	cost int
}
//Make 加密方法
func (b *Bcrypt) Make(password []byte) ([]byte, error) {
	return bcrypt.GenerateFromPassword(password, b.cost)
}
//Check 检查方法
func (b *Bcrypt) Check(hashedPassword, password []byte) error {
	return bcrypt.CompareHashAndPassword(hashedPassword, password)
}

pkg/hash/bcrypt_test.go

package hash

import (
	"fmt"
	"testing"
)

func TestNewHash(t *testing.T) {
    //实例化结构体
    hash := Bcrypt{
        cost: bcrypt.DefaultCost
    }
    //模拟密码
	password := "123456"
    //加密
	bytes, err := hash.Make([]byte(password))
	if err != nil {
		t.Error(err)
		return
	}
	fmt.Println(string(bytes))
    
	//检查明文是否为加密密码的明文
	err = hash.Check(bytes, []byte(password))
	if err != nil {
		t.Error(err)
	}
	fmt.Println("密码正确")
}