Golang 中的 Bcrypt 密码散列(与 Node.js 兼容)?

Posted

技术标签:

【中文标题】Golang 中的 Bcrypt 密码散列(与 Node.js 兼容)?【英文标题】:Bcrypt password hashing in Golang (compatible with Node.js)? 【发布时间】:2014-06-09 04:31:36 【问题描述】:

我使用 Node.js+passport 设置了一个站点以进行用户身份验证。

现在我需要迁移到 Golang,并且需要使用保存在 db 中的用户密码进行身份验证。

Node.js 加密代码为:

    var bcrypt = require('bcrypt');

    bcrypt.genSalt(10, function(err, salt) 
        if(err) return next(err);

        bcrypt.hash(user.password, salt, function(err, hash) 
            if(err) return next(err);
            user.password = hash;
            next();
        );
    );

如何使用 Golang 制作与 Node.js bcrypt 相同的哈希字符串?

【问题讨论】:

【参考方案1】:

看看来自go.crypto 的bcrypt package(文档是here)。

要安装它,请使用

go get golang.org/x/crypto/bcrypt

可以在here 找到描述 bcrypt 包用法的博客条目。它来自编写包的人,所以它应该可以工作;)

与您使用的 node.js 库的一个区别是 go 包没有(导出的)genSalt 函数,但是当您调用 bcrypt.GenerateFromPassword 时它会自动生成盐。

【讨论】:

【参考方案2】:

使用 golang.org/x/crypto/bcrypt 包,我相信等价于:

hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)

工作示例:

package main

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

func main() 
    password := []byte("MyDarkSecret")

    // Hashing the password with the default cost of 10
    hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
    if err != nil 
        panic(err)
    
    fmt.Println(string(hashedPassword))

    // Comparing the password with the hash
    err = bcrypt.CompareHashAndPassword(hashedPassword, password)
    fmt.Println(err) // nil means it is a match

【讨论】:

谢谢。我使用 bcrypt.CompareHashAndPassword 比较密码和 node.js 在db中写入的字符串,并返回 nil。本来我以为生成的字符串总是一样的。现在我明白了。真的很感激。 @user2036213:我之前也从未使用过 bcrypt,每次运行都会为相同的密码生成一个新的哈希,这让我有点惊讶。但它仍然可以正常工作。我们每天都在学习新事物:)。 Go 编码快乐! 呃,这就是随机盐的好处——确保两个具有相同密码的用户不会有相同的(加盐的)哈希。 Here 是一篇很长但很好的背景文章。 @rob74:我明白了。我错过了一个事实,即 bcrypt 生成的哈希包括 bcrypt 版本、成本、盐和密码,而不仅仅是密码 (***.com/a/6833165/694331)。感谢您的文章! @majidarif 比较时,字符串也会被散列;这是设计使然。创建散列和比较散列具有相同的成本。我会说它按预期工作:)【参考方案3】:

首先你需要导入 bcrypt 包

go get golang.org/x/crypto/bcrypt

然后使用 GenerateFromPassword

bs, err := bcrypt.GenerateFromPassword([]byte(p), bcrypt.MinCost)
    if err != nil 
        http.Error(w, "Internal server error", http.StatusInternalServerError)
        return
    

【讨论】:

以上是关于Golang 中的 Bcrypt 密码散列(与 Node.js 兼容)?的主要内容,如果未能解决你的问题,请参考以下文章

Bcrypt 是用于散列还是加密?有点迷茫

使用 bcrypt 散列密码迁移系统

我应该使用啥列类型/长度将 Bcrypt 散列密码存储在数据库中?

javascript 用于散列密码的Bcrypt助手

bcrypt 哈希究竟如何防止彩虹表查找?

javascript 使用带有promises的bcrypt来散列密码,然后验证它