Go实现随机加盐密码认证

为什么要加密

人们往往有使用同一密码的习惯, 为了防止数据库意外泄露/破坏和出于保护用户隐私的目的, 不应在数据库里存入用户密码明文

实现

代码
package main

import (
	"fmt"
	"golang.org/x/crypto/bcrypt"
	"time"
)

func main() {
	password := []byte("thisIsPassWord")
	nowG := time.Now()
	hashedPassword, _ := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
	fmt.Println("加密后", string(hashedPassword), "耗时", time.Now().Sub(nowG))
	nowC := time.Now()
	err := bcrypt.CompareHashAndPassword(hashedPassword, password)
	fmt.Println("验证耗费时间", time.Now().Sub(nowC))
	fmt.Println(err)
}

// 结果
// 加密后 $2a$10$ESkb/bwSyISLgq1bOH0C2utXdb.hcH9oBQD1hUnfDOzm4bMKK6EX2 耗时 67.9985ms
// 验证耗费时间 66.0008ms
// <nil>  

将加密后的密码串存入数据表, 然后用户登录传递明文密码(也可以前段加密后端再解密成明文)进行验证

密码串解析
$2a$10$ESkb/bwSyISLgq1bOH0C2utXdb.hcH9oBQD1hUnfDOzm4bMKK6EX2
$ 为分隔符
2a bcrypt加密版本号
10 Cost值
ESkb/bwSyISLgq1bOH0C2utXdb 盐
hcH9oBQD1hUnfDOzm4bMKK6EX2 密码密文
优缺点
优点:
    单向HASH,不可解密
    盐值随机(有效防止彩虹表碰撞)
    破解时间成本极高
缺点:
    效率较慢(相较于mad5/sha算法)
源码分析
// GenerateFromPassword returns the bcrypt hash of the password at the given
// cost. If the cost given is less than MinCost, the cost will be set to
// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
// to compare the returned hashed password with its cleartext version.
func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
	p, err := newFromPassword(password, cost)
	if err != nil {
		return nil, err
	}
	return p.Hash(), nil
}

// CompareHashAndPassword compares a bcrypt hashed password with its possible
// plaintext equivalent. Returns nil on success, or an error on failure.
func CompareHashAndPassword(hashedPassword, password []byte) error {
	p, err := newFromHash(hashedPassword)
	if err != nil {
		return err
	}

	otherHash, err := bcrypt(password, p.cost, p.salt)
	if err != nil {
		return err
	}

	otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
	if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
		return nil
	}

	return ErrMismatchedHashAndPassword
}

就是用已有的加密哈希的salt和cost对现有密码进行加密来确认密码密文是否一致

补充
1 最主要还是得用户的密码设置复杂一些(可以考虑强制), 最好是大小写加特殊字符, 还有就是提醒用户尽量不同网站用不同的密码
2 可以在密码里面加一些固有字段, 也能提升安全等级, 比如在前后或者在中间加参数再进行加密解密(用户不改我们帮他改)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个示例代码,用于演示如何在golang实现基本的用户密码登录和加密储存功能: ```go package main import ( "fmt" "golang.org/x/crypto/bcrypt" ) var users = map[string]string{ "alice": "123456", "bob": "password", "eve": "qwerty", } func login(username, password string) bool { // 检查用户名是否存在 if hashedPassword, ok := users[username]; ok { // 检查密码是否正确 if err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)); err == nil { return true } } return false } func register(username, password string) error { // 生成随机salt, err := bcrypt.GenerateFromPassword([]byte(username), bcrypt.DefaultCost) if err != nil { return err } // 哈希密码并保存 hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return err } users[username] = string(hashedPassword) return nil } func main() { // 测试注册和登录功能 username := "charlie" password := "zxcvbn" err := register(username, password) if err != nil { fmt.Printf("注册失败: %v\n", err) return } if login(username, password) { fmt.Printf("%s 登录成功\n", username) } else { fmt.Printf("%s 登录失败\n", username) } } ``` 在上面的代码中,我们使用了golang的`bcrypt`包来对密码进行哈希和验证。在`register`函数中,我们首先生成一个随机盐,并使用该盐和给定的密码生成哈希密码。然后,我们将用户名和哈希密码存储在`users`map中。 在`login`函数中,我们首先检查给定的用户名是否存在于`users`map中。如果存在,我们将存储的哈希密码和给定的密码进行比较。如果密码匹配,该函数返回`true`,否则返回`false`。 在`main`函数中,我们使用`register`函数注册了一个新用户,并使用`login`函数测试了该用户的登录过程。请注意,由于我们使用了随机盐和哈希密码,这种方法比简单密码储存更安全。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小僵尸打字员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值