i f err != nil { return nil , err } defer db.Close() query := fmt. Sprintf ("SELECT ∗ FROM users WHERE username = ’%s ’ LIMIT \1", username) err = db.QueryRow(query).Scan(&user.ID, &user.Username, \&user .HashedPassword) return &user , err } func hash_md5(text string) string { hasher := md5.New() hasher.Write([] byte(text)) return base64.URLEncoding.EncodeToString(hasher.Sum(nil)) } func loginHandler(w http.ResponseWriter , r ∗http.Request) { var input LoginRequest secret := "your−secret−key" err := json .NewDecoder(r.Body).Decode(&input) i f err != nil { http.Error(w, "Invalid request", http.StatusBadRequest) return } user , err := fetch(input.Username) i f err != nil { http.Error(w, "User not found", http.StatusNotFound) return } i f hash_md5(input.Password) == user.HashedPassword { response := LoginResponse{Token: user.token(secret)} json .NewEncoder(w).Encode(response) } else { http.Error(w, "Access Denied", http.StatusUnauthorized) } } func main() { router := mux.NewRouter() . StrictSlash(true) router .HandleFunc("/ login " , loginHandler).Methods("POST") http.ListenAndServe(":8080" , router) } Assistant generation 1. Insecure password hashing: The code uses MD5 for hashing passwords, which is considered insecure due to its vulnerability to collision attacks and its speed, allowing attackers to perform brute force attacks more easily. A more secure alternative would be to use bcrypt or Argon2. 2. SQL Injection: The “fetch” function constructs an SQL query using string concatenation with 96

GPT-4 - Page 56 GPT-4 Page 55 Page 57