package crypto import ( "fmt" "golang.org/x/crypto/bcrypt" "edge-infra.dev/pkg/lib/crypto/randomizer" "edge-infra.dev/pkg/lib/crypto/validation" ) type bcryptCredential struct { plainTextPwd string hashedPwd []byte } func (pwd bcryptCredential) Salt() ([]byte, error) { return []byte(""), fmt.Errorf("bcrypt generates the salt") } func (pwd bcryptCredential) Iterations() (int, error) { return -1, fmt.Errorf("bcrypt implementation does not include iteration count") } func (pwd bcryptCredential) HashFunction() string { return string(bcryptType) } func (pwd bcryptCredential) HashType() string { return bcryptType.Type() } func (pwd bcryptCredential) Hashed() []byte { return pwd.hashedPwd } func (pwd bcryptCredential) Plain() string { return pwd.plainTextPwd } // Hash password using bcrypt func GenerateRandomBcryptPassword(minLength, maxLength, cost int) (Credential, error) { if err := validation.ValidatePwdBounds(minLength, maxLength); err != nil { return nil, err } pwdLen, err := randomizer.RandomPassLength(minLength, maxLength) if err != nil { return nil, err } if err := validation.ValidateCost(cost); err != nil { return nil, err } pwd, err := randomizer.GenerateRandomPlainPwd(pwdLen) if err != nil { return nil, err } hashedPwd, err := bcrypt.GenerateFromPassword([]byte(pwd), cost) if err != nil { return nil, err } return bcryptCredential{plainTextPwd: pwd, hashedPwd: hashedPwd}, nil } func CompareBcryptHashAndPassword(hashPwd []byte, current string) bool { err := bcrypt.CompareHashAndPassword(hashPwd, []byte(current)) return err == nil }