Secure Budget Manager

What I Built:

  • A client-server application using sockets
  • User login and account creation system
  • Password hashing using SHA-256
  • Basic encryption/decryption for data transmission
  • Budget tracking system with stored user data

Key Skills Demonstrated:

  • Secure authentication implementation
  • Client-server communication (sockets)
  • Data encryption and protection
  • File handling and persistence (JSON)
  • Python programming for security-focused applications

What I Learned:

  • Importance of hashing passwords instead of storing plaintext
  • How client-server systems communicate securely
  • Challenges of handling authentication and user data
  • Basics of securing data in transit and at rest


server.py

import socket

import json

import hashlib

import os

# Encryption/Decryption functions

def encrypt(data, key=5):

    return ”.join(chr(ord(c) ^ key) for c in data)

def decrypt(data, key=5):

    return encrypt(data, key)

# Load users from file

def load_users():

    try:

        with open(“users.json”, “r”) as f:

            return json.load(f)

    except FileNotFoundError:

        return {}

# Save users to file

def save_users(users):

    with open(“users.json”, “w”) as f:

        json.dump(users, f)

# Hash password

def hash_password(password):

    return hashlib.sha256(password.encode()).hexdigest()

# Authenticate user login

def authenticate(username, password_hash, users):

    if username in users:

        return users[username][“password”] == password_hash

    return False

# Create account

def create_account(username, password_hash, users):

    users[username] = {“password”: password_hash}

    save_users(users)

    return True

# Calculate recommended 50/30/20 budget

def calculate_budget(income):

    return {

        “needs”: round(income * 0.50, 2),

        “wants”: round(income * 0.30, 2),

        “savings”: round(income * 0.20, 2)

    }

# Compare actual vs recommended expenses

def analyze_expenses(recommended, actual):

    analysis = {}

    if actual[“needs”] > recommended[“needs”]:

        analysis[“needs_status”] = f”Over budget by ${round(actual[‘needs’] – recommended[‘needs’], 2)}”

    else:

        analysis[“needs_status”] = “Within recommended budget”

    if actual[“wants”] > recommended[“wants”]:

        analysis[“wants_status”] = f”Over budget by ${round(actual[‘wants’] – recommended[‘wants’], 2)}”

    else:

        analysis[“wants_status”] = “Within recommended budget”

    if actual[“savings”] < recommended[“savings”]:

        analysis[“savings_status”] = f”Below recommended savings by ${round(recommended[‘savings’] – actual[‘savings’], 2)}”

    else:

        analysis[“savings_status”] = “Meeting or exceeding savings goal”

    return analysis

def save_budget_to_file(username, income, budget, actual, analysis):

    filename = f”{username}_budget_history.json”

    # Load existing history or create new

    if os.path.exists(filename):

        with open(filename, “r”) as f:

            history = json.load(f)

    else:

        history = []

    entry = {

        “income”: income,

        “recommended_budget”: budget,

        “actual_expenses”: actual,

        “analysis”: analysis

    }

    history.append(entry)

    with open(filename, “w”) as f:

        json.dump(history, f, indent=4)

# Main server function

def start_server(host=”127.0.0.1″, port=12345):

    users = load_users()

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    server_socket.bind((host, port))

    server_socket.listen()

    print(f”Server running on {host}:{port}…”)

    while True:

        conn, addr = server_socket.accept()

        print(f”Connected to {addr}”)

        try:

            login_data = decrypt(conn.recv(1024).decode())

            username, password_hash, action = login_data.split(“,”)

            if action == “login”:

                if authenticate(username, password_hash, users):

                    conn.send(encrypt(“SUCCESS”).encode())

                else:

                    conn.send(encrypt(“FAIL”).encode())

                    conn.close()

                    continue

            elif action == “create”:

                if username in users:

                    conn.send(encrypt(“EXISTS”).encode())

                    conn.close()

                    continue

                else:

                    create_account(username, password_hash, users)

                    conn.send(encrypt(“CREATED”).encode())

            encrypted_income = conn.recv(1024).decode()

            income = float(decrypt(encrypted_income))

            budget = calculate_budget(income)

            conn.send(encrypt(json.dumps(budget)).encode())

            expenses_encrypted = conn.recv(1024).decode()

            actual_expenses = json.loads(decrypt(expenses_encrypted))

            analysis = analyze_expenses(budget, actual_expenses)

            

            save_budget_to_file(username, income, budget, actual_expenses, analysis)

            conn.send(encrypt(json.dumps(analysis)).encode())

        except Exception as e:

            print(“Error:”, e)

        finally:

            conn.close()

            print(f”Disconnected from {addr}”)

if __name__ == “__main__”:

    start_server()


client .py
import socket

import json

SHIFT = 4

def encrypt(text):

    return “”.join(chr((ord(c) + SHIFT) % 256) for c in text)

def decrypt(text):

    return “”.join(chr((ord(c) – SHIFT) % 256) for c in text)

def send_request(sock, data):

    encrypted = encrypt(json.dumps(data))

    sock.send(encrypted.encode())

    response = decrypt(sock.recv(4096).decode())

    return json.loads(response)

# —————————–

# MAIN CLIENT

# —————————–

def main():

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    sock.connect((“127.0.0.1”, 5000))

    print(“\n— Welcome to the Budget Tracker —“)

    print(“1. Login”)

    print(“2. Create Account”)

    choice = input(“Choose: “)

    username = input(“Username: “)

    password = input(“Password: “)

    if choice == “1”:

        res = send_request(sock, {“action”: “login”, “username”: username, “password”: password})

    else:

        res = send_request(sock, {“action”: “register”, “username”: username, “password”: password})

    if res[“status”] != “ok”:

        print(res[“msg”])

        return

    print(“\nLogged in successfully!\n”)

    while True:

        print(“\n— Menu —“)

        print(“1. Add Expense”)

        print(“2. View Expense History”)

        print(“3. Calculate 50/30/20 Budget”)

        print(“4. Exit”)

        option = input(“Choose: “)

        if option == “1”:

            item = input(“Expense name: “)

            amount = float(input(“Amount: “))

            res = send_request(sock, {“action”: “add_expense”, “username”: username, “item”: item, “amount”: amount})

            print(res[“msg”])

        elif option == “2”:

            res = send_request(sock, {“action”: “get_history”, “username”: username})

            print(“\n— Expense History —“)

            for e in res[“history”]:

                print(f”{e[‘item’]}: ${e[‘amount’]}”)

        elif option == “3”:

            income = float(input(“Monthly income: $”))

            res = send_request(sock, {“action”: “budget”, “username”: username, “income”: income})

            print(“\n— 50/30/20 Breakdown —“)

            print(f”Needs:   ${res[‘needs’]:.2f}”)

            print(f”Wants:   ${res[‘wants’]:.2f}”)

            print(f”Savings: ${res[‘savings’]:.2f}”)

        elif option == “4”:

            print(“Goodbye!”)

            sock.close()

            break

        else:

            print(“Invalid choice.”)

if __name__ == “__main__”:

    main()

Milestone-1

Leave a Reply

Your email address will not be published. Required fields are marked *