mirror of
https://github.com/kopia/kopia.git
synced 2025-12-23 22:57:50 -05:00
72 lines
1.8 KiB
Go
72 lines
1.8 KiB
Go
package user
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"io"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type passwordHash struct {
|
|
PasswordHashVersion int `json:"passwordHashVersion"`
|
|
PasswordHash []byte `json:"passwordHash"`
|
|
}
|
|
|
|
// HashPassword computes the hash for the given password and an encoded hash
|
|
// that can be passed to Profile.SetPasswordHash().
|
|
func HashPassword(password string) (string, error) {
|
|
const hashVersion = defaultPasswordHashVersion
|
|
|
|
salt := make([]byte, passwordHashSaltLength)
|
|
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
|
|
return "", errors.Wrap(err, "error generating salt")
|
|
}
|
|
|
|
h, err := computePasswordHash(password, salt, hashVersion)
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "error hashing password")
|
|
}
|
|
|
|
pwh := passwordHash{
|
|
PasswordHashVersion: hashVersion,
|
|
PasswordHash: h,
|
|
}
|
|
|
|
j, err := json.Marshal(pwh)
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "error encoding password hash")
|
|
}
|
|
|
|
return base64.StdEncoding.EncodeToString(j), nil
|
|
}
|
|
|
|
func decodeHashedPassword(encodedHash string) (*passwordHash, error) {
|
|
var h passwordHash
|
|
|
|
passwordHashJSON, err := base64.StdEncoding.DecodeString(encodedHash)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "decoding password hash")
|
|
}
|
|
|
|
if err := json.Unmarshal(passwordHashJSON, &h); err != nil {
|
|
return nil, errors.Wrap(err, "unmarshaling password hash")
|
|
}
|
|
|
|
return &h, nil
|
|
}
|
|
|
|
// validates hashing algorithm and password hash length.
|
|
func (h *passwordHash) validate() error {
|
|
if _, err := getPasswordHashAlgorithm(h.PasswordHashVersion); err != nil {
|
|
return errors.Wrap(err, "invalid password hash version")
|
|
}
|
|
|
|
if len(h.PasswordHash) != passwordHashSaltLength+passwordHashLength {
|
|
return errors.Errorf("invalid hash length: %v", len(h.PasswordHash))
|
|
}
|
|
|
|
return nil
|
|
}
|