using bcrypt

jocadbz
Joca 2025-12-07 21:30:23 -03:00
parent 7b934e00a6
commit 876ac33d1b
Signed by: jocadbz
GPG Key ID: B1836DCE2F50BDF7
1 changed files with 46 additions and 23 deletions

View File

@ -1,10 +1,13 @@
package models package models
import ( import (
"crypto/rand"
"crypto/sha256" "crypto/sha256"
"database/sql" "database/sql"
"fmt" "fmt"
"time" "time"
"golang.org/x/crypto/bcrypt"
) )
type User struct { type User struct {
@ -22,6 +25,12 @@ type User struct {
Permissions int64 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) { 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 = ?" 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) 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 { func CheckPassword(password, salt, algorithm, hash string) bool {
if algorithm != "sha256" { switch algorithm {
return false case "bcrypt":
} return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) == nil
case "sha256":
computedHash := HashPassword(password, salt, algorithm) computedHash := HashPassword(password, salt, algorithm)
return computedHash == hash return computedHash == hash
default:
return false
}
} }
func HashPassword(password, salt, algorithm string) string { func HashPassword(password, salt, algorithm string) string {
if algorithm != "sha256" { switch algorithm {
return "" case "sha256":
}
data := password + salt data := password + salt
hash := sha256.Sum256([]byte(data)) hash := sha256.Sum256([]byte(data))
return fmt.Sprintf("%x", hash) return fmt.Sprintf("%x", hash)
default:
return ""
}
} }
func CreateUser(db *sql.DB, username, password string) error { func CreateUser(db *sql.DB, username, password string) error {
salt := "random-salt" // Replace with secure random generation hash, err := bcrypt.GenerateFromPassword([]byte(password), bcryptCost)
algorithm := "sha256" if err != nil {
hash := HashPassword(password, salt, algorithm) 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)" 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 return err
} }