From 876ac33d1bee2256c24bcce8e2139c27aa3e565d Mon Sep 17 00:00:00 2001 From: Jocadbz Date: Sun, 7 Dec 2025 21:30:23 -0300 Subject: [PATCH] using bcrypt --- models/user.go | 69 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/models/user.go b/models/user.go index 281867c..a7a2f1d 100644 --- a/models/user.go +++ b/models/user.go @@ -1,27 +1,36 @@ package models import ( + "crypto/rand" "crypto/sha256" "database/sql" "fmt" "time" + + "golang.org/x/crypto/bcrypt" ) type User struct { - ID int - Username string - DisplayName string - PfpFileID sql.NullInt64 - Bio string - AuthenticationString string - AuthenticationSalt string + ID int + Username string + DisplayName string + PfpFileID sql.NullInt64 + Bio string + AuthenticationString string + AuthenticationSalt string AuthenticationAlgorithm string - CreatedAt time.Time - UpdatedAt time.Time - Verified bool - Permissions int64 + CreatedAt time.Time + UpdatedAt time.Time + Verified bool + Permissions int64 } +const ( + // bcryptCost defines the work factor for bcrypt password hashing. + // 12 is a reasonable default; increase for stronger machines. + bcryptCost = 12 +) + func GetUserByID(db *sql.DB, id int) (*User, error) { query := "SELECT id, username, display_name, pfp_file_id, bio, authentication_string, authentication_salt, authentication_algorithm, created_at, updated_at, verified, permissions FROM users WHERE id = ?" row := db.QueryRow(query, id) @@ -108,28 +117,42 @@ func GetUserByUsername(db *sql.DB, username string) (*User, error) { } func CheckPassword(password, salt, algorithm, hash string) bool { - if algorithm != "sha256" { + switch algorithm { + case "bcrypt": + return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) == nil + case "sha256": + computedHash := HashPassword(password, salt, algorithm) + return computedHash == hash + default: return false } - computedHash := HashPassword(password, salt, algorithm) - return computedHash == hash } func HashPassword(password, salt, algorithm string) string { - if algorithm != "sha256" { + switch algorithm { + case "sha256": + data := password + salt + hash := sha256.Sum256([]byte(data)) + return fmt.Sprintf("%x", hash) + default: return "" } - data := password + salt - hash := sha256.Sum256([]byte(data)) - return fmt.Sprintf("%x", hash) } func CreateUser(db *sql.DB, username, password string) error { - salt := "random-salt" // Replace with secure random generation - algorithm := "sha256" - hash := HashPassword(password, salt, algorithm) + hash, err := bcrypt.GenerateFromPassword([]byte(password), bcryptCost) + if err != nil { + return err + } + // Keep salt column for backward compatibility, or else this apparently shits itself + var saltBytes [16]byte + if _, err := rand.Read(saltBytes[:]); err != nil { + return fmt.Errorf("failed to generate salt: %w", err) + } + salt := fmt.Sprintf("%x", saltBytes) + query := "INSERT INTO users (username, authentication_string, authentication_salt, authentication_algorithm, created_at, updated_at, verified, permissions) VALUES (?, ?, ?, ?, NOW(), NOW(), ?, 0)" - _, err := db.Exec(query, username, hash, salt, algorithm, false) + _, err = db.Exec(query, username, string(hash), salt, "bcrypt", false) return err } @@ -176,4 +199,4 @@ func GetUsernamesInBoard(db *sql.DB, boardID int) ([]string, error) { usernames = append(usernames, username) } return usernames, nil -} \ No newline at end of file +}