package auth

import (
	"crypto/sha256"
	"crypto/subtle"
	"errors"

	"golang.org/x/crypto/pbkdf2"
)

var ErrPasswordTooShort = errors.New("password must be non-empty")

type HashedPassword struct {
	hash []byte
}

func (hp HashedPassword) Bytes() []byte {
	return hp.hash
}

func (hp HashedPassword) Equals(other HashedPassword) bool {
	return subtle.ConstantTimeCompare(hp.hash, other.hash) != 0
}

func HashPassword(password string) (HashedPassword, error) {
	if len(password) == 0 {
		return HashedPassword{}, ErrPasswordTooShort
	}

	// These bytes are chosen at random. It's insecure to use a static salt to
	// hash a set of passwords, but since we're only ever hashing a single
	// password, using a static salt is fine. The salt prevents an attacker from
	// using a rainbow table to retrieve the plaintext password from the hashed
	// version, and that's all that's necessary for fusion's needs.
	staticSalt := []byte{36, 129, 1, 54}
	iter := 100
	keyLen := 32
	hash := pbkdf2.Key([]byte(password), staticSalt, iter, keyLen, sha256.New)

	return HashedPassword{
		hash: hash,
	}, nil
}
