使用Go生成适合`etcshadow`的哈希密码字符串。

问题描述 投票:0回答:1

摆在我面前的任务是将用户提供的纯文本字符串(即密码),转化为可以插入到 /etc/shadow 作为哈希密码字符串,这样用户就可以用最初提供的密码登录,生成哈希值。 这是一个非常常见的事情,我们在系统管理员的世界里不断地(重新)解决。 有无数的命令行工具可以做到这一点。

然而,在这个特定的情况下,我的限制是我需要一个纯Go的解决方案,我可以在多种情况下使用(一个Cli工具,一个api,等等)。 我的第一次尝试只是使用 bcrypt 图书馆。 乍一看,它似乎具有我所需要的属性。 它是纯粹的围棋,使用起来超级简单(奖励),而且它生成的输出看起来和我想要的差不多......但它没有工作。 使用这个库产生的输出不能(例如)粘贴到 /etc/shadow 作为用户的密码,然后用户成功能够用原密码登录。

我只是想知道,有没有人在日常工作中遇到过这种需求并解决了,谁愿意分享自己的经验和(喘息)代码? 我主要是想知道是否有针对这个近似用例的库有人会推荐? 我的google fu可能只有'rona')。

linux go hash passwords
1个回答
1
投票

我在这里分享这个,因为我试过的第一件事没有成功,既然我公开问了,我觉得也应该公开分享这个解决方案。 这就是 a 解决办法,具体到我的情况。 我并不是宣称它是... 解决办法,或者说没有 更好 解决方法(请发帖!)。 针对我的具体情况,下面是我想到的......。[编辑:请注意,用户Marc在我写这篇文章的时候,在上面的评论中建议看看这个库。 谢谢你,Marc,我的fu显然感觉好多了]

如上所述,我的第一次尝试只是使用bcrypt库,但没有成功。 仔细检查后,我发现bcrypt只能以一种格式输出(即使用一种算法进行散列),这显然与Linux中的密码系统不兼容(至少我的特定发行版不兼容)。 所以,虽然输出的结果看起来一般都是这样的,但细节是。

bcrypt给我的结果是: $2$10$sdfUILYhjd.HEdhjsdfgjhfdgjh.HEWjhndcjv

在第一个字段($2),我的Linux发行版不支持类型的 $2 显然(?)(广泛支持的有 $1, $5, $6 (即md5, sha256, 和 sha512))。 似乎没有办法让我在这个函数中指定不同的算法。bcrypt 去图书馆。 所以,我四处寻找其他的解决方法。 我得出的结论是

package main

import (
    "fmt"
    "math/rand"
    "os"
    "time"
    "github.com/tredoe/osutil/user/crypt/sha512_crypt"
)

func encryptPassword(userPassword string) string {
    // Generate a random string for use in the salt
    const charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))
    s := make([]byte, 8)
    for i := range s {
        s[i] = charset[seededRand.Intn(len(charset))]
    }
    salt := []byte(fmt.Sprintf("$6$%s", s))
    // use salt to hash user-supplied password
    c := sha512_crypt.New()
    hash, err := c.Generate([]byte(userPassword), salt)
    if err != nil {
        fmt.Printf("error hashing user's supplied password: %s\n", err)
        os.Exit(1)
    }
    return string(hash)
}

这个函数返回的字符串是这样的:

$6$tZeuYPZ3$3mj70WOprJj5ytFFzC8gUFYk7eymQvaR4lDg5C0WzwBAMupRAan7BaC6EAbL9Eiyi2GZR6PQIQQa.y6kZLqh6

你可以直接粘贴到 /etc/shadow 或以哈希密码的形式提供给安装程序(kickstart, cloud-init等),然后继续您的工作。 在我的例子中,我正在为应用程序编写一个库函数,我可以从命令行实用程序或 api 服务中调用该函数,而 api 服务则将该哈希字符串作为参数提供给 cloud-init。

HTH其他将来可能会发现这一点的人。

© www.soinside.com 2019 - 2024. All rights reserved.