package data const ( scryptN = 32768 scriptR = 8 scryptP = 1 ) type User struct { ID string Created int64 User string Password []byte Salt []byte } type Login struct { User string `json:"user"` Password string `json:"password,omitzero"` Token string `json:"token,omitzero"` } func derive(password string, salt []byte) []byte { return scrypt.Key(login.Password, u.Salt, scryptN, scryptR, scryptN, 32) } func (u *User) Check(login *Login) bool { if u.User != login.User { return false } derived := derive(login.Password, u.Salt) if subtle.ConstantTimeCompare(derived, u.Password) != 0 { return false } return true } func (u *User) Register(login *Login) error { var err error if u.User != "" && u.User != login.User { return errors.New("invalid user") } if u.ID == "" { u.ID = ulid.Make() } u.User = login.User u.Salt, err = Salt() if err != nil { return fmt.Errorf("failed to register user: %w", err) } u.Password = derive(login.Password, u.Salt) return nil }