Table of Contents
问题内容
解决方法
Home Backend Development Golang Use Go to verify passwords based on hashed passwords in the /etc/shadow file

Use Go to verify passwords based on hashed passwords in the /etc/shadow file

Feb 08, 2024 pm 11:54 PM
go language

使用 Go 根据 /etc/shadow 文件中的哈希密码验证密码

php小编子墨今天为大家介绍一种使用Go语言验证密码的方法,这个方法是基于读取/etc/shadow文件中的哈希密码进行验证的。在日常开发中,密码验证是一个非常重要的功能,而使用Go语言可以快速、高效地实现密码验证的功能。通过读取/etc/shadow文件中的哈希密码并进行比对,我们可以确保用户输入的密码与存储在系统中的密码一致。本文将详细介绍这个方法的实现过程,希望能对大家有所帮助。

问题内容

我目前在 /etc/shadow 文件中的密码格式类似于 $6$icnb6xpt8xjwc$ai9rq5hqpep.juts/tubhk/oi7so/s1aa.ihgbjhn12qmt5p44x5or86pso9/opbo4cmo0at4xumc0ycapo8 7/sha512加密密码)。我需要做的是验证密码(用户提供的密码和当前的哈希密码)。我正在 go 上实现这个。

我试图实现这一目标的方法是,获取用户提供的密码,使用与 /etc/shadow 中相同的盐对其进行哈希处理,并检查它们是否相似或不同。如何生成相同的哈希值并验证密码?

下面是我正在做的粗略代码(根据 amadan 对编码的评论进行了更新)

// this is what is stored on /etc/shadow - a hashed string of "test"
myPwd := "$6$IcnB6XpT8xjWC$AI9Rq5hqpEP.Juts/TUbHk/OI7sO/S1AA.ihgBjHN12QmT5p44X5or86PsO9/oPBO4cmo0At4XuMC0yCApo87/"
// getting the salt
salt := strings.Split(myPwd, "$")[2]


encoding := base64.NewEncoding("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz").WithPadding(base64.NoPadding)
decodedSalt, err := encoding.DecodeString(salt)

// user provided password
myNewPwd := "test"

newHashedPwd, err := hashPwd512(string(myNewPwd), string(decodedSalt))

// comparision
if (newHashedPwd == myPwd) {
   // password is same, validate it
}

// What I'm expecting from this method is that for the same password stored in the /etc/shadow, 
// and the same salt, it should return (like the one in /etc/shadow file)
// AI9Rq5hqpEP.Juts/TUbHk/OI7sO/S1AA.ihgBjHN12QmT5p44X5or86PsO9/oPBO4cmo0At4XuMC0yCApo87/

func hashPwd512(pwd string, salt string) (string, error) {
    hash := sha512.New()
    hash.Write([]byte(salt))
    hash.Write([]byte(pwd))

    encoding := base64.NewEncoding("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz").WithPadding(base64.NoPadding)

    hashedPwd := encoding.EncodeToString(hash.Sum(nil))
    return hashedPwd, nil
}
Copy after login

注意:密码通过passwdchpasswd设置/更改。

解决方法

sha512 是一种快速哈希。这对密码来说是不利的,因为当每次尝试几乎不需要花费任何成本时,暴力破解就变得非常容易。为了减慢速度,/etc/shadow 中的内容不仅仅是一个简单的 sha512 哈希值,而是 key拉伸适用于哈希算法运行数千次的情况。具体的密钥拉伸算法好像是这个。因此,crypto/sha512 只完成了所需任务的大约 1/5000(默认情况下)。

幸运的是,已经有人做了艰苦的工作;您可以在此处查看其实现。

package main

import (
    "fmt"
    "strings"

    "github.com/gehirninc/crypt"
    _ "github.com/gehirninc/crypt/sha512_crypt"
)

func main() {
    saltedpass := "$6$icnb6xpt8xjwc$ai9rq5hqpep.juts/tubhk/oi7so/s1aa.ihgbjhn12qmt5p44x5or86pso9/opbo4cmo0at4xumc0ycapo87/"
    fmt.println("original: ", saltedpass)

    // make new hash from scratch
    plainpass := "test"
    crypt := crypt.sha512.new()
    newsaltedpass, err := crypt.generate([]byte(plainpass), []byte(saltedpass))
    if err != nil {
        panic(err)
    }
    fmt.println("generated:", newsaltedpass)

    // verify a password (correct)
    err = crypt.verify(saltedpass, []byte(plainpass))
    fmt.println("verification error (correct password):  ", err)

    // verify a password (incorrect)
    badpass := "fail"
    err = crypt.verify(saltedpass, []byte(badpass))
    fmt.println("verification error (incorrect password):", err)
}
Copy after login

由于您只需要验证,因此 verify 快捷方式就足够了(它会在幕后为您生成 generate):

err = crypt.verify(saltedpass, []byte(plainpass))
if err == nil {
    fmt.println("fly, you fools!")
} else {
    fmt.println("you shall not pass!")
}
Copy after login

输出:

Original:  $6$IcnB6XpT8xjWC$AI9Rq5hqpEP.Juts/TUbHk/OI7sO/S1AA.ihgBjHN12QmT5p44X5or86PsO9/oPBO4cmo0At4XuMC0yCApo87/
Generated: $6$IcnB6XpT8xjWC$AI9Rq5hqpEP.Juts/TUbHk/OI7sO/S1AA.ihgBjHN12QmT5p44X5or86PsO9/oPBO4cmo0At4XuMC0yCApo87/
Verification error (correct password):   <nil>
Verification error (incorrect password): hashed value is not the hash of the given password
Copy after login

注意:我相信我的评论是错误的。密码哈希本身就是通过这种编码进行编码的,但盐似乎是真正的盐(只是当它随机生成时,使用了该编码中的字符)。

该库还支持其他哈希函数,但您确实需要为每个函数进行导入才能注册它。您还可以看到,我没有费心从 saltedpass 中分离盐;这也是您不需要担心的事情。

但是,如果您出于某种原因确实想隔离盐,那么还要注意,从一开始就计算 $ 并不是一个安全的想法,因为它将无法处理像 $6$rounds=77777$ 这样的条目例如,正确地短 $wuqyw2yr.hbnpjjrhpyd/ifiw05xdfeeyqomxixbkvr0g 。使用 strings.lastindex(saltedpass, "$") + 1 作为切入点。

The above is the detailed content of Use Go to verify passwords based on hashed passwords in the /etc/shadow file. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
Two Point Museum: All Exhibits And Where To Find Them
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Which libraries in Go are developed by large companies or provided by well-known open source projects? Which libraries in Go are developed by large companies or provided by well-known open source projects? Apr 02, 2025 pm 04:12 PM

Which libraries in Go are developed by large companies or well-known open source projects? When programming in Go, developers often encounter some common needs, ...

What is the problem with Queue thread in Go's crawler Colly? What is the problem with Queue thread in Go's crawler Colly? Apr 02, 2025 pm 02:09 PM

Queue threading problem in Go crawler Colly explores the problem of using the Colly crawler library in Go language, developers often encounter problems with threads and request queues. �...

In Go, why does printing strings with Println and string() functions have different effects? In Go, why does printing strings with Println and string() functions have different effects? Apr 02, 2025 pm 02:03 PM

The difference between string printing in Go language: The difference in the effect of using Println and string() functions is in Go...

What libraries are used for floating point number operations in Go? What libraries are used for floating point number operations in Go? Apr 02, 2025 pm 02:06 PM

The library used for floating-point number operation in Go language introduces how to ensure the accuracy is...

How to solve the problem that custom structure labels in Goland do not take effect? How to solve the problem that custom structure labels in Goland do not take effect? Apr 02, 2025 pm 12:51 PM

Regarding the problem of custom structure tags in Goland When using Goland for Go language development, you often encounter some configuration problems. One of them is...

Why is it necessary to pass pointers when using Go and viper libraries? Why is it necessary to pass pointers when using Go and viper libraries? Apr 02, 2025 pm 04:00 PM

Go pointer syntax and addressing problems in the use of viper library When programming in Go language, it is crucial to understand the syntax and usage of pointers, especially in...

Why do all values ​​become the last element when using for range in Go language to traverse slices and store maps? Why do all values ​​become the last element when using for range in Go language to traverse slices and store maps? Apr 02, 2025 pm 04:09 PM

Why does map iteration in Go cause all values ​​to become the last element? In Go language, when faced with some interview questions, you often encounter maps...

What is the difference between `var` and `type` keyword definition structure in Go language? What is the difference between `var` and `type` keyword definition structure in Go language? Apr 02, 2025 pm 12:57 PM

Two ways to define structures in Go language: the difference between var and type keywords. When defining structures, Go language often sees two different ways of writing: First...

See all articles