# secure_server.py from flask import Flask, request, abort import json app = Flask(__name__) SECRET_KEY = "LAB2_SUPER_SECRET_MAC_KEY" # this is shared only between the node and the server def compute_mac(payload: str) -> int: """ Very simple (non-crypto!) MAC: hash(payload + SECRET_KEY) This is just for teaching integrity, not real security. """ data = (payload + SECRET_KEY).encode("utf-8", errors="ignore") h = 0 for b in data: h = (h * 31) ^ b h &= 0xFFFFFFFF # keep as 32-bit return h @app.route("/ingest", methods=["POST"]) def ingest(): raw_body = request.data.decode("utf-8", errors="ignore") print("=== New HTTPS request ===") print("Client IP:", request.remote_addr) print("Headers:") for k, v in request.headers.items(): print(f" {k}: {v}") print("Raw body:", raw_body) try: data = json.loads(raw_body) except json.JSONDecodeError: print("!! Invalid JSON, rejecting") abort(400, "Invalid JSON") # Expect fields: device_id, temp_c, humidity, battery, mac if "mac" not in data: print("!! Missing MAC, rejecting") abort(400, "Missing MAC") received_mac = int(data["mac"]) # Compute MAC over body without the mac field check_obj = dict(data) del check_obj["mac"] # Use a canonical payload string for MAC computation mac_payload = json.dumps(check_obj, sort_keys=True, separators=(",", ":")) expected_mac = compute_mac(mac_payload) print(f"Received MAC: {received_mac}") print(f"Expected MAC: {expected_mac}") if received_mac != expected_mac: print("!! MAC mismatch, possible tampering, rejecting") abort(403, "Invalid MAC") print("MAC OK, accepting data:", check_obj) print("=========================") return "OK\n" if __name__ == "__main__": # HTTPS on 8443, replace IP with your own server's address app.run( host="0.0.0.0", port=8443, ssl_context=("server.crt", "server.key") )