{"id":585,"date":"2026-04-30T03:22:50","date_gmt":"2026-04-30T03:22:50","guid":{"rendered":"https:\/\/sites.wp.odu.edu\/zsumu001\/?p=585"},"modified":"2026-04-30T04:20:39","modified_gmt":"2026-04-30T04:20:39","slug":"secure-budget-manager","status":"publish","type":"post","link":"https:\/\/sites.wp.odu.edu\/zsumu001\/2026\/04\/30\/secure-budget-manager\/","title":{"rendered":"Secure Budget Manager"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">What I Built:<\/h3>\n\n\n\n<ul>\n<li>A client-server application using sockets<\/li>\n\n\n\n<li>User login and account creation system<\/li>\n\n\n\n<li>Password hashing using SHA-256<\/li>\n\n\n\n<li>Basic encryption\/decryption for data transmission<\/li>\n\n\n\n<li>Budget tracking system with stored user data<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Key Skills Demonstrated:<\/h3>\n\n\n\n<ul>\n<li>Secure authentication implementation<\/li>\n\n\n\n<li>Client-server communication (sockets)<\/li>\n\n\n\n<li>Data encryption and protection<\/li>\n\n\n\n<li>File handling and persistence (JSON)<\/li>\n\n\n\n<li>Python programming for security-focused applications<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">What I Learned:<\/h3>\n\n\n\n<ul>\n<li>Importance of hashing passwords instead of storing plaintext<\/li>\n\n\n\n<li>How client-server systems communicate securely<\/li>\n\n\n\n<li>Challenges of handling authentication and user data<\/li>\n\n\n\n<li>Basics of securing data in transit and at rest<\/li>\n<\/ul>\n\n\n\n<p><br>server.py<\/p>\n\n\n\n<p>import socket<\/p>\n\n\n\n<p>import json<\/p>\n\n\n\n<p>import hashlib<\/p>\n\n\n\n<p>import os<\/p>\n\n\n\n<p># Encryption\/Decryption functions<\/p>\n\n\n\n<p>def encrypt(data, key=5):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return &#8221;.join(chr(ord(c) ^ key) for c in data)<\/p>\n\n\n\n<p>def decrypt(data, key=5):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return encrypt(data, key)<\/p>\n\n\n\n<p># Load users from file<\/p>\n\n\n\n<p>def load_users():<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;try:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with open(&#8220;users.json&#8221;, &#8220;r&#8221;) as f:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return json.load(f)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;except FileNotFoundError:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return {}<\/p>\n\n\n\n<p># Save users to file<\/p>\n\n\n\n<p>def save_users(users):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;with open(&#8220;users.json&#8221;, &#8220;w&#8221;) as f:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;json.dump(users, f)<\/p>\n\n\n\n<p># Hash password<\/p>\n\n\n\n<p>def hash_password(password):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return hashlib.sha256(password.encode()).hexdigest()<\/p>\n\n\n\n<p># Authenticate user login<\/p>\n\n\n\n<p>def authenticate(username, password_hash, users):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;if username in users:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return users[username][&#8220;password&#8221;] == password_hash<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return False<\/p>\n\n\n\n<p># Create account<\/p>\n\n\n\n<p>def create_account(username, password_hash, users):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;users[username] = {&#8220;password&#8221;: password_hash}<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;save_users(users)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return True<\/p>\n\n\n\n<p># Calculate recommended 50\/30\/20 budget<\/p>\n\n\n\n<p>def calculate_budget(income):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return {<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;needs&#8221;: round(income * 0.50, 2),<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;wants&#8221;: round(income * 0.30, 2),<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;savings&#8221;: round(income * 0.20, 2)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;}<\/p>\n\n\n\n<p># Compare actual vs recommended expenses<\/p>\n\n\n\n<p>def analyze_expenses(recommended, actual):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;analysis = {}<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;if actual[&#8220;needs&#8221;] &gt; recommended[&#8220;needs&#8221;]:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;analysis[&#8220;needs_status&#8221;] = f&#8221;Over budget by ${round(actual[&#8216;needs&#8217;] &#8211; recommended[&#8216;needs&#8217;], 2)}&#8221;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;else:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;analysis[&#8220;needs_status&#8221;] = &#8220;Within recommended budget&#8221;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;if actual[&#8220;wants&#8221;] &gt; recommended[&#8220;wants&#8221;]:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;analysis[&#8220;wants_status&#8221;] = f&#8221;Over budget by ${round(actual[&#8216;wants&#8217;] &#8211; recommended[&#8216;wants&#8217;], 2)}&#8221;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;else:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;analysis[&#8220;wants_status&#8221;] = &#8220;Within recommended budget&#8221;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;if actual[&#8220;savings&#8221;] &lt; recommended[&#8220;savings&#8221;]:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;analysis[&#8220;savings_status&#8221;] = f&#8221;Below recommended savings by ${round(recommended[&#8216;savings&#8217;] &#8211; actual[&#8216;savings&#8217;], 2)}&#8221;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;else:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;analysis[&#8220;savings_status&#8221;] = &#8220;Meeting or exceeding savings goal&#8221;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return analysis<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>def save_budget_to_file(username, income, budget, actual, analysis):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;filename = f&#8221;{username}_budget_history.json&#8221;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;# Load existing history or create new<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;if os.path.exists(filename):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with open(filename, &#8220;r&#8221;) as f:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;history = json.load(f)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;else:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;history = []<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;entry = {<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;income&#8221;: income,<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;recommended_budget&#8221;: budget,<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;actual_expenses&#8221;: actual,<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8220;analysis&#8221;: analysis<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;}<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;history.append(entry)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;with open(filename, &#8220;w&#8221;) as f:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;json.dump(history, f, indent=4)<\/p>\n\n\n\n<p># Main server function<\/p>\n\n\n\n<p>def start_server(host=&#8221;127.0.0.1&#8243;, port=12345):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;users = load_users()<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;server_socket.bind((host, port))<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;server_socket.listen()<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;Server running on {host}:{port}&#8230;&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;while True:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn, addr = server_socket.accept()<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;Connected to {addr}&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;login_data = decrypt(conn.recv(1024).decode())<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;username, password_hash, action = login_data.split(&#8220;,&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if action == &#8220;login&#8221;:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if authenticate(username, password_hash, users):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.send(encrypt(&#8220;SUCCESS&#8221;).encode())<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.send(encrypt(&#8220;FAIL&#8221;).encode())<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.close()<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elif action == &#8220;create&#8221;:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if username in users:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.send(encrypt(&#8220;EXISTS&#8221;).encode())<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.close()<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;create_account(username, password_hash, users)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.send(encrypt(&#8220;CREATED&#8221;).encode())<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;encrypted_income = conn.recv(1024).decode()<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;income = float(decrypt(encrypted_income))<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;budget = calculate_budget(income)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.send(encrypt(json.dumps(budget)).encode())<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expenses_encrypted = conn.recv(1024).decode()<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;actual_expenses = json.loads(decrypt(expenses_encrypted))<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;analysis = analyze_expenses(budget, actual_expenses)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;save_budget_to_file(username, income, budget, actual_expenses, analysis)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.send(encrypt(json.dumps(analysis)).encode())<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except Exception as e:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;Error:&#8221;, e)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;finally:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.close()<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;Disconnected from {addr}&#8221;)<\/p>\n\n\n\n<p>if __name__ == &#8220;__main__&#8221;:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;start_server()<\/p>\n\n\n\n<p><br>client .py<br>import socket<\/p>\n\n\n\n<p>import json<\/p>\n\n\n\n<p>SHIFT = 4<\/p>\n\n\n\n<p>def encrypt(text):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return &#8220;&#8221;.join(chr((ord(c) + SHIFT) % 256) for c in text)<\/p>\n\n\n\n<p>def decrypt(text):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return &#8220;&#8221;.join(chr((ord(c) &#8211; SHIFT) % 256) for c in text)<\/p>\n\n\n\n<p>def send_request(sock, data):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;encrypted = encrypt(json.dumps(data))<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;sock.send(encrypted.encode())<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;response = decrypt(sock.recv(4096).decode())<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return json.loads(response)<\/p>\n\n\n\n<p># &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<\/p>\n\n\n\n<p># MAIN CLIENT<\/p>\n\n\n\n<p># &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<\/p>\n\n\n\n<p>def main():<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;sock.connect((&#8220;127.0.0.1&#8221;, 5000))<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;\\n&#8212; Welcome to the Budget Tracker &#8212;&#8220;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;1. Login&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;2. Create Account&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;choice = input(&#8220;Choose: &#8220;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;username = input(&#8220;Username: &#8220;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;password = input(&#8220;Password: &#8220;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;if choice == &#8220;1&#8221;:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res = send_request(sock, {&#8220;action&#8221;: &#8220;login&#8221;, &#8220;username&#8221;: username, &#8220;password&#8221;: password})<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;else:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res = send_request(sock, {&#8220;action&#8221;: &#8220;register&#8221;, &#8220;username&#8221;: username, &#8220;password&#8221;: password})<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;if res[&#8220;status&#8221;] != &#8220;ok&#8221;:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(res[&#8220;msg&#8221;])<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;\\nLogged in successfully!\\n&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;while True:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;\\n&#8212; Menu &#8212;&#8220;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;1. Add Expense&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;2. View Expense History&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;3. Calculate 50\/30\/20 Budget&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;4. Exit&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;option = input(&#8220;Choose: &#8220;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if option == &#8220;1&#8221;:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item = input(&#8220;Expense name: &#8220;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;amount = float(input(&#8220;Amount: &#8220;))<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res = send_request(sock, {&#8220;action&#8221;: &#8220;add_expense&#8221;, &#8220;username&#8221;: username, &#8220;item&#8221;: item, &#8220;amount&#8221;: amount})<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(res[&#8220;msg&#8221;])<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elif option == &#8220;2&#8221;:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res = send_request(sock, {&#8220;action&#8221;: &#8220;get_history&#8221;, &#8220;username&#8221;: username})<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;\\n&#8212; Expense History &#8212;&#8220;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for e in res[&#8220;history&#8221;]:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;{e[&#8216;item&#8217;]}: ${e[&#8216;amount&#8217;]}&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elif option == &#8220;3&#8221;:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;income = float(input(&#8220;Monthly income: $&#8221;))<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res = send_request(sock, {&#8220;action&#8221;: &#8220;budget&#8221;, &#8220;username&#8221;: username, &#8220;income&#8221;: income})<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;\\n&#8212; 50\/30\/20 Breakdown &#8212;&#8220;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;Needs: &nbsp; ${res[&#8216;needs&#8217;]:.2f}&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;Wants: &nbsp; ${res[&#8216;wants&#8217;]:.2f}&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f&#8221;Savings: ${res[&#8216;savings&#8217;]:.2f}&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elif option == &#8220;4&#8221;:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;Goodbye!&#8221;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sock.close()<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(&#8220;Invalid choice.&#8221;)<\/p>\n\n\n\n<p>if __name__ == &#8220;__main__&#8221;:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;main()<\/p>\n\n\n<a href=\"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-content\/uploads\/sites\/31974\/2026\/04\/Milestone-1.pdf\" class=\"pdfemb-viewer\" style=\"\" data-width=\"max\" data-height=\"max\"  data-toolbar=\"bottom\" data-toolbar-fixed=\"off\">Milestone-1<br\/><\/a>\n<p class=\"wp-block-pdfemb-pdf-embedder-viewer\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>What I Built: Key Skills Demonstrated: What I Learned: server.py import socket import json import hashlib import os # Encryption\/Decryption functions def encrypt(data, key=5): &nbsp;&nbsp;&nbsp;&nbsp;return &#8221;.join(chr(ord(c) ^ key) for c <a class=\"more-link\" href=\"https:\/\/sites.wp.odu.edu\/zsumu001\/2026\/04\/30\/secure-budget-manager\/\">Continue Reading &rarr;<\/a><\/p>\n","protected":false},"author":25872,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","wds_primary_category":0},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-json\/wp\/v2\/posts\/585"}],"collection":[{"href":"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-json\/wp\/v2\/users\/25872"}],"replies":[{"embeddable":true,"href":"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-json\/wp\/v2\/comments?post=585"}],"version-history":[{"count":4,"href":"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-json\/wp\/v2\/posts\/585\/revisions"}],"predecessor-version":[{"id":642,"href":"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-json\/wp\/v2\/posts\/585\/revisions\/642"}],"wp:attachment":[{"href":"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-json\/wp\/v2\/media?parent=585"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-json\/wp\/v2\/categories?post=585"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sites.wp.odu.edu\/zsumu001\/wp-json\/wp\/v2\/tags?post=585"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}