1
0
mirror of https://github.com/muety/wakapi.git synced 2023-08-10 21:12:56 +03:00

feat: use bcrypt with salts instead of md5 for hashing password (resolve #21)

This commit is contained in:
Ferdinand Mütsch 2020-05-25 21:42:45 +02:00
parent 625994d1e9
commit 08675bd99f
9 changed files with 30 additions and 22 deletions

View File

@ -5,5 +5,6 @@ WAKAPI_DB_USER=myuser
WAKAPI_DB_PASSWORD=shhh WAKAPI_DB_PASSWORD=shhh
WAKAPI_DB_HOST=localhost WAKAPI_DB_HOST=localhost
WAKAPI_DB_PORT=3306 WAKAPI_DB_PORT=3306
WAKAPI_PASSWORD_SALT=shhh
WAKAPI_DEFAULT_USER_NAME=admin WAKAPI_DEFAULT_USER_NAME=admin
WAKAPI_DEFAULT_USER_PASSWORD=admin # CHANGE! WAKAPI_DEFAULT_USER_PASSWORD=admin123 # CHANGE!

View File

@ -4,7 +4,7 @@ port = 3000
base_path = / base_path = /
[app] [app]
cleanup = true cleanup = false
[database] [database]
max_connections = 2 max_connections = 2

1
go.mod
View File

@ -16,5 +16,6 @@ require (
github.com/rubenv/sql-migrate v0.0.0-20200402132117-435005d389bc github.com/rubenv/sql-migrate v0.0.0-20200402132117-435005d389bc
github.com/satori/go.uuid v1.2.0 github.com/satori/go.uuid v1.2.0
github.com/t-tiger/gorm-bulk-insert v0.0.0-20191014134946-beb77b81825f github.com/t-tiger/gorm-bulk-insert v0.0.0-20191014134946-beb77b81825f
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c
gopkg.in/ini.v1 v1.50.0 gopkg.in/ini.v1 v1.50.0
) )

View File

@ -101,7 +101,7 @@ func (m *AuthenticateMiddleware) tryGetUserByCookie(r *http.Request) (*models.Us
if err != nil { if err != nil {
return nil, err return nil, err
} }
if !utils.CheckPassword(user, login.Password) { if !utils.CheckPassword(user, login.Password, m.config.PasswordSalt) {
return nil, errors.New("invalid password") return nil, errors.New("invalid password")
} }
} else { } else {

View File

@ -30,6 +30,7 @@ type Config struct {
CleanUp bool CleanUp bool
DefaultUserName string DefaultUserName string
DefaultUserPassword string DefaultUserPassword string
PasswordSalt string
SecureCookieHashKey string SecureCookieHashKey string
SecureCookieBlockKey string SecureCookieBlockKey string
CustomLanguages map[string]string CustomLanguages map[string]string
@ -86,6 +87,7 @@ func readConfig() *Config {
dbHost := LookupFatal("WAKAPI_DB_HOST") dbHost := LookupFatal("WAKAPI_DB_HOST")
dbName := LookupFatal("WAKAPI_DB_NAME") dbName := LookupFatal("WAKAPI_DB_NAME")
dbPortStr := LookupFatal("WAKAPI_DB_PORT") dbPortStr := LookupFatal("WAKAPI_DB_PORT")
passwordSalt := LookupFatal("WAKAPI_PASSWORD_SALT")
defaultUserName := LookupFatal("WAKAPI_DEFAULT_USER_NAME") defaultUserName := LookupFatal("WAKAPI_DEFAULT_USER_NAME")
defaultUserPassword := LookupFatal("WAKAPI_DEFAULT_USER_PASSWORD") defaultUserPassword := LookupFatal("WAKAPI_DEFAULT_USER_PASSWORD")
dbPort, err := strconv.Atoi(dbPortStr) dbPort, err := strconv.Atoi(dbPortStr)
@ -162,6 +164,7 @@ func readConfig() *Config {
DbMaxConn: dbMaxConn, DbMaxConn: dbMaxConn,
CleanUp: cleanUp, CleanUp: cleanUp,
SecureCookie: secureCookie, SecureCookie: secureCookie,
PasswordSalt: passwordSalt,
DefaultUserName: defaultUserName, DefaultUserName: defaultUserName,
DefaultUserPassword: defaultUserPassword, DefaultUserPassword: defaultUserPassword,
CustomLanguages: customLangs, CustomLanguages: customLangs,

View File

@ -76,7 +76,7 @@ func (h *IndexHandler) Login(w http.ResponseWriter, r *http.Request) {
return return
} }
if !utils.CheckPassword(user, login.Password) { if !utils.CheckPassword(user, login.Password, h.config.PasswordSalt) {
respondAlert(w, "invalid credentials", "", "", http.StatusUnauthorized) respondAlert(w, "invalid credentials", "", "", http.StatusUnauthorized)
return return
} }

View File

@ -1,10 +1,9 @@
package services package services
import ( import (
"crypto/md5"
"encoding/hex"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/muety/wakapi/models" "github.com/muety/wakapi/models"
"github.com/muety/wakapi/utils"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
) )
@ -47,14 +46,14 @@ func (srv *UserService) GetAll() ([]*models.User, error) {
} }
func (srv *UserService) CreateOrGet(signup *models.Signup) (*models.User, bool, error) { func (srv *UserService) CreateOrGet(signup *models.Signup) (*models.User, bool, error) {
pw := md5.Sum([]byte(signup.Password))
pwString := hex.EncodeToString(pw[:])
apiKey := uuid.NewV4().String()
u := &models.User{ u := &models.User{
ID: signup.Username, ID: signup.Username,
ApiKey: apiKey, ApiKey: uuid.NewV4().String(),
Password: pwString, Password: signup.Password,
}
if err := utils.HashPassword(u, srv.Config.PasswordSalt); err != nil {
return nil, false, err
} }
result := srv.Db.FirstOrCreate(u, &models.User{ID: u.ID}) result := srv.Db.FirstOrCreate(u, &models.User{ID: u.ID})

View File

@ -1,11 +1,10 @@
package utils package utils
import ( import (
"crypto/md5"
"encoding/base64" "encoding/base64"
"encoding/hex"
"errors" "errors"
"github.com/muety/wakapi/models" "github.com/muety/wakapi/models"
"golang.org/x/crypto/bcrypt"
"net/http" "net/http"
"regexp" "regexp"
"strings" "strings"
@ -55,11 +54,16 @@ func ExtractCookieAuth(r *http.Request, config *models.Config) (login *models.Lo
return login, nil return login, nil
} }
func CheckPassword(user *models.User, password string) bool { func CheckPassword(user *models.User, password, salt string) bool {
passwordHash := md5.Sum([]byte(password)) err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password+salt))
passwordHashString := hex.EncodeToString(passwordHash[:]) return err == nil
if passwordHashString == user.Password { }
return true
} // inplace
return false func HashPassword(u *models.User, salt string) error {
bytes, err := bcrypt.GenerateFromPassword([]byte(u.Password+salt), bcrypt.DefaultCost)
if err == nil {
u.Password = string(bytes)
}
return err
} }

View File

@ -1 +1 @@
1.4.1 1.5.0