using bcrypt
parent
7b934e00a6
commit
876ac33d1b
|
|
@ -1,27 +1,36 @@
|
||||||
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 {
|
||||||
ID int
|
ID int
|
||||||
Username string
|
Username string
|
||||||
DisplayName string
|
DisplayName string
|
||||||
PfpFileID sql.NullInt64
|
PfpFileID sql.NullInt64
|
||||||
Bio string
|
Bio string
|
||||||
AuthenticationString string
|
AuthenticationString string
|
||||||
AuthenticationSalt string
|
AuthenticationSalt string
|
||||||
AuthenticationAlgorithm string
|
AuthenticationAlgorithm string
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
Verified bool
|
Verified bool
|
||||||
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 {
|
||||||
|
case "bcrypt":
|
||||||
|
return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) == nil
|
||||||
|
case "sha256":
|
||||||
|
computedHash := HashPassword(password, salt, algorithm)
|
||||||
|
return computedHash == hash
|
||||||
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
computedHash := HashPassword(password, salt, algorithm)
|
|
||||||
return computedHash == hash
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func HashPassword(password, salt, algorithm string) string {
|
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 ""
|
return ""
|
||||||
}
|
}
|
||||||
data := password + salt
|
|
||||||
hash := sha256.Sum256([]byte(data))
|
|
||||||
return fmt.Sprintf("%x", hash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,4 +199,4 @@ func GetUsernamesInBoard(db *sql.DB, boardID int) ([]string, error) {
|
||||||
usernames = append(usernames, username)
|
usernames = append(usernames, username)
|
||||||
}
|
}
|
||||||
return usernames, nil
|
return usernames, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue