util: password: Add a helper to generate salted, hashed passwords

I have no idea if I'm doing this correctly, and I have no idea if the
library I am using is doing this correctly. Please check!
This commit is contained in:
James Shubin
2024-03-07 17:33:00 -05:00
parent 9351eee3f1
commit b496f8d70a
3 changed files with 33 additions and 0 deletions

View File

@@ -36,10 +36,12 @@ import (
"io"
"os"
"runtime"
"strings"
"sync"
"syscall"
"time"
sha512Crypt "github.com/tredoe/osutil/v2/userutil/crypt/sha512_crypt"
"golang.org/x/sys/unix"
)
@@ -152,3 +154,31 @@ func ReadPasswordCtxFdPrompt(ctx context.Context, fd int, prompt string) ([]byte
}
}
}
// SaltedSHA512Password is meant to generate Ulrich Drepper's salted SHA512 unix
// crypt password hash as seen at https://www.akkadia.org/drepper/SHA-crypt.txt
// and used for /etc/shadow and anaconda kickstart files. Please read the
// following disclaimer carefully before using this: XXX: I have no idea if I am
// doing this correctly, and I have no idea if the library I am using is doing
// this correctly. Please check! Also: https://github.com/golang/go/issues/21865
func SaltedSHA512Password(password []byte) (string, error) {
crypter := sha512Crypt.New()
saltObj := sha512Crypt.GetSalt() // New() builds us one, this is another
crypter.SetSalt(saltObj)
salt := saltObj.GenerateWRounds(sha512Crypt.SaltLenMax, sha512Crypt.RoundsDefault)
// NOTE: We could pass an empty salt and the above should happen, but we
// wouldn't notice it if the API changed and no longer did this magic...
hash, err := crypter.Generate(password, salt)
if err != nil {
return "", err
}
if len(hash) != 106 { // XXX: the rounds=? stuff feels not part of spec
return "", fmt.Errorf("password was not generated correctly")
}
if !strings.HasPrefix(hash, sha512Crypt.MagicPrefix) {
// programming error
return "", fmt.Errorf("magic prefix was missing")
}
return hash, nil
}