Использование Go для генерации строк хешированных паролей, подходящих для `/ etc / shadow` - PullRequest
0 голосов
/ 29 мая 2020

Передо мной стоит задача взять введенную пользователем строку в виде обычного текста (например, пароль) и превратить ее во что-то, что можно вставить в /etc/shadow как строку хешированного пароля, чтобы пользователь мог затем войти in с паролем, изначально предоставленным для генерации ha sh. Это очень распространенная проблема, которую мы (повторно) решаем снова и снова в мире системных администраторов. Для этого существует множество утилит командной строки.

В этом конкретном случае c, однако, мое ограничение состоит в том, что мне нужно чистое Go решение, которое я могу использовать в нескольких контекстах (инструмент cli, api и т.д. c). Моя первая попытка заключалась в том, чтобы просто использовать библиотеку bcrypt. На первый взгляд казалось, что он обладает необходимыми мне атрибутами. Он чистый Go, его очень просто использовать (бонус), и он генерирует вывод, который выглядит примерно так, как я хотел ... но это не сработало. Результат, полученный в результате использования этой библиотеки, нельзя (например) вставить в /etc/shadow в качестве пароля пользователя, после чего пользователь сможет успешно войти в систему с исходным паролем.

Мне просто интересно, сталкивался ли кто-нибудь с этой потребностью в повседневной жизни и решал ее, кто готов поделиться своим опытом и ( g asp) код? В основном мне интересно, есть ли библиотека, ориентированная на этот примерный вариант использования, который кто-то порекомендовал бы? (у моего гугл-фу может быть просто 'рона).

1 Ответ

1 голос
/ 29 мая 2020

Я делюсь этим здесь, потому что первое, что я попробовал, не сработало, и, поскольку я публично спросил, я счел справедливым также публично поделиться решением. Это решение , конкретное c для моей ситуации. Я не утверждаю, что это решение или что нет лучших решений (пожалуйста, опубликуйте их!). Для моей конкретной ситуации c вот что я придумал ... [ EDIT : обратите внимание, что пользователь Mar c предложил посмотреть на эту библиотеку в комментарии выше, пока я писал это. Спасибо, мар c, моя фу явно лучше]

Как уже говорилось, моей первой попыткой было просто использовать библиотеку bcrypt, но это не сработало. При ближайшем рассмотрении я обнаружил, что bcrypt выводит только в одном формате (т.е. использует один алгоритм для хеширования), который явно НЕ совместим с системой паролей в Linux (по крайней мере, не в моем конкретном дистрибутиве). Таким образом, хотя результат в целом выглядел так, как должен, детали были следующими:

bcrypt дает мне что-то вроде: $2$10$sdfUILYhjd.HEdhjsdfgjhfdgjh.HEWjhndcjv

В этом первом поле ($2) мой дистрибутив Linux не поддерживает тип $2 по-видимому (?) (Широко поддерживаются $1, $5, $6 (т.е. md5, sha256 и sha512)). Мне показалось, что у меня не было способа указать другой алгоритм в библиотеке bcrypt go. Итак, я стал искать другие подходы / решения. Я пришел к следующему:

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, et c) и go о вашей компании. В моем случае я пишу библиотечную функцию для приложения, которое я могу вызвать из утилиты командной строки или из службы api, которая, в свою очередь, предоставляет эту хешированную строку в качестве параметра для cloud-init.

HTH другие, которые могут найти это в будущем.

...