From 6f96d45b7e9269957abcc888ba269ec87408fffe Mon Sep 17 00:00:00 2001 From: Kenneth Chew Date: Thu, 20 Apr 2023 18:00:56 -0400 Subject: [PATCH] Use salts for passwords in account creation and validation --- api/database.sql | 3 ++- api/login/login.go | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/api/database.sql b/api/database.sql index 87eae9f..56f92b9 100644 --- a/api/database.sql +++ b/api/database.sql @@ -2,7 +2,8 @@ CREATE TABLE Accounts ( email VARCHAR(50) PRIMARY KEY, firstName VARCHAR(50), lastName VARCHAR(50), - password CHAR(64) NOT NULL + password CHAR(64) NOT NULL, + salt CHAR(16) NOT NULL ); CREATE TABLE Chats ( id INTEGER PRIMARY KEY, diff --git a/api/login/login.go b/api/login/login.go index 0864078..a47cbb1 100644 --- a/api/login/login.go +++ b/api/login/login.go @@ -3,6 +3,7 @@ package login import ( "api/auth" "api/database" + "crypto/rand" "os" "encoding/json" @@ -33,8 +34,12 @@ func createAccount(response http.ResponseWriter, request *http.Request) { return } - result, err := database.Execute("INSERT INTO Accounts (email, password) VALUES (?, SHA2(?, 256))", acc.Email, acc.Password) + salt := generateSalt() + saltedPassword := acc.Password + salt + + result, err := database.Execute("INSERT INTO Accounts (email, password, salt) VALUES (?, SHA2(?, 256), ?)", acc.Email, saltedPassword, salt) if err != nil { + log.Println(err) return } @@ -59,7 +64,14 @@ func validateAccount(response http.ResponseWriter, request *http.Request) { return } - token, err := auth.GetToken(acc.Email, acc.Password) + salt, err := getSalt(acc.Email) + if err != nil { + fmt.Fprint(response, FAILURE_RESPONSE) + return + } + saltedPassword := acc.Password + salt + + token, err := auth.GetToken(acc.Email, saltedPassword) if err != nil { fmt.Fprint(response, FAILURE_RESPONSE) @@ -76,6 +88,22 @@ func validateAccount(response http.ResponseWriter, request *http.Request) { fmt.Fprint(response, tokenString) } +// Returns a secure random salt that is 16 characters long. +func generateSalt() string { + b := make([]byte, 8) + rand.Read(b) + return fmt.Sprintf("%x", b) +} + +func getSalt(email string) (string, error) { + salt := "" + err := database.QueryValue(&salt, "SELECT salt FROM Accounts WHERE email = ?", email) + if err != nil || salt == "" { + return "", err + } + return salt, nil +} + func HandleLoginRoutes(r *mux.Router) { r.HandleFunc("/login/createAccount", createAccount).Methods("POST") r.HandleFunc("/login/validateAccount", validateAccount).Methods("POST")